1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Synchronization tests for resources shared between instances.
22 *//*--------------------------------------------------------------------*/
24 #include "vktSynchronizationCrossInstanceSharingTests.hpp"
26 #include "vkDeviceUtil.hpp"
27 #include "vkPlatform.hpp"
28 #include "vkCmdUtil.hpp"
29 #include "vktTestCaseUtil.hpp"
30 #include "deSharedPtr.hpp"
32 #include "vktSynchronizationUtil.hpp"
33 #include "vktSynchronizationOperation.hpp"
34 #include "vktSynchronizationOperationTestData.hpp"
35 #include "vktSynchronizationOperationResources.hpp"
36 #include "vktExternalMemoryUtil.hpp"
37 #include "vktTestGroupUtil.hpp"
38 #include "vktCustomInstancesDevices.hpp"
40 #include "deRandom.hpp"
42 #include "tcuResultCollector.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuCommandLine.hpp"
47 using namespace vkt::ExternalMemoryUtil;
51 namespace synchronization
60 TestConfig (const ResourceDescription& resource_,
61 vk::VkSemaphoreType semaphoreType_,
62 OperationName writeOp_,
63 OperationName readOp_,
64 vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType_,
65 vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreHandleType_,
67 : resource (resource_)
68 , semaphoreType (semaphoreType_)
71 , memoryHandleType (memoryHandleType_)
72 , semaphoreHandleType (semaphoreHandleType_)
73 , dedicated (dedicated_)
77 const ResourceDescription resource;
78 const vk::VkSemaphoreType semaphoreType;
79 const OperationName writeOp;
80 const OperationName readOp;
81 const vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType;
82 const vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreHandleType;
86 // A helper class to test for extensions upfront and throw not supported to speed up test runtimes compared to failing only
87 // after creating unnecessary vkInstances. A common example of this is win32 platforms taking a long time to run _fd tests.
88 class NotSupportedChecker
91 NotSupportedChecker (const Context& context,
93 const OperationSupport& writeOp,
94 const OperationSupport& readOp)
97 // Check instance support
98 m_context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
100 m_context.requireInstanceFunctionality("VK_KHR_external_semaphore_capabilities");
101 m_context.requireInstanceFunctionality("VK_KHR_external_memory_capabilities");
103 // Check device support
104 if (config.dedicated)
105 m_context.requireDeviceFunctionality("VK_KHR_dedicated_allocation");
107 m_context.requireDeviceFunctionality("VK_KHR_external_semaphore");
108 m_context.requireDeviceFunctionality("VK_KHR_external_memory");
110 if (config.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE_KHR)
112 m_context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
115 if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
116 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
117 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
119 m_context.requireDeviceFunctionality("VK_KHR_external_semaphore_fd");
120 m_context.requireDeviceFunctionality("VK_KHR_external_memory_fd");
123 if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
125 m_context.requireDeviceFunctionality("VK_EXT_external_memory_dma_buf");
128 if (config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
129 || config.memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR
130 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
131 || config.semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
133 m_context.requireDeviceFunctionality("VK_KHR_external_semaphore_win32");
134 m_context.requireDeviceFunctionality("VK_KHR_external_memory_win32");
137 TestLog& log = context.getTestContext().getLog();
138 const vk::InstanceInterface& vki = context.getInstanceInterface();
139 const vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
141 // Check resource support
142 if (config.resource.type == RESOURCE_TYPE_IMAGE)
144 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
146 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
148 config.memoryHandleType
150 const vk::VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
152 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
154 config.resource.imageFormat,
155 config.resource.imageType,
156 vk::VK_IMAGE_TILING_OPTIMAL,
157 readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
160 vk::VkExternalImageFormatProperties externalProperties =
162 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
166 vk::VkImageFormatProperties2 formatProperties =
168 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
180 const vk::VkResult res = vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &formatProperties);
182 if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
183 TCU_THROW(NotSupportedError, "Image format not supported");
185 VK_CHECK(res); // Check other errors
188 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
190 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
191 TCU_THROW(NotSupportedError, "Exporting image resource not supported");
193 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
194 TCU_THROW(NotSupportedError, "Importing image resource not supported");
196 if (!config.dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
198 TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
203 const vk::VkPhysicalDeviceExternalBufferInfo info =
205 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
209 readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
210 config.memoryHandleType
212 vk::VkExternalBufferProperties properties =
214 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
218 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
220 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
222 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0
223 || (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
224 TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported");
226 if (!config.dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
228 TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
232 // Check semaphore support
234 const vk::VkSemaphoreTypeCreateInfoKHR semaphoreTypeInfo =
236 vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR,
238 config.semaphoreType,
241 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
243 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
245 config.semaphoreHandleType
248 vk::VkExternalSemaphoreProperties properties =
250 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
257 vki.getPhysicalDeviceExternalSemaphoreProperties(physicalDevice, &info, &properties);
259 log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
261 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0
262 || (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
263 TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported");
269 const Context& m_context;
272 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
274 if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
275 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT;
277 return (availableFlags & neededFlags) != 0;
280 class SimpleAllocation : public vk::Allocation
283 SimpleAllocation (const vk::DeviceInterface& vkd,
285 const vk::VkDeviceMemory memory);
286 ~SimpleAllocation (void);
289 const vk::DeviceInterface& m_vkd;
290 const vk::VkDevice m_device;
293 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface& vkd,
295 const vk::VkDeviceMemory memory)
296 : Allocation (memory, 0, DE_NULL)
302 SimpleAllocation::~SimpleAllocation (void)
304 m_vkd.freeMemory(m_device, getMemory(), DE_NULL);
307 CustomInstance createTestInstance (Context& context)
309 std::vector<std::string> extensions;
310 extensions.push_back("VK_KHR_get_physical_device_properties2");
311 extensions.push_back("VK_KHR_external_semaphore_capabilities");
312 extensions.push_back("VK_KHR_external_memory_capabilities");
314 return createCustomInstanceWithExtensions(context, extensions);
317 vk::Move<vk::VkDevice> createTestDevice (const Context& context,
318 const vk::PlatformInterface& vkp,
319 vk::VkInstance instance,
320 const vk::InstanceInterface& vki,
321 const vk::VkPhysicalDevice physicalDevice)
323 const bool validationEnabled = context.getTestContext().getCommandLine().isValidationEnabled();
324 const float priority = 0.0f;
325 const std::vector<vk::VkQueueFamilyProperties> queueFamilyProperties = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
326 std::vector<deUint32> queueFamilyIndices (queueFamilyProperties.size(), 0xFFFFFFFFu);
327 std::vector<const char*> extensions;
329 if (context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
330 extensions.push_back("VK_KHR_dedicated_allocation");
332 if (context.isDeviceFunctionalitySupported("VK_KHR_get_memory_requirements2"))
333 extensions.push_back("VK_KHR_get_memory_requirements2");
335 if (context.isDeviceFunctionalitySupported("VK_KHR_external_semaphore"))
336 extensions.push_back("VK_KHR_external_semaphore");
337 if (context.isDeviceFunctionalitySupported("VK_KHR_external_memory"))
338 extensions.push_back("VK_KHR_external_memory");
340 if (context.isDeviceFunctionalitySupported("VK_KHR_external_semaphore_fd"))
341 extensions.push_back("VK_KHR_external_semaphore_fd");
342 if (context.isDeviceFunctionalitySupported("VK_KHR_external_memory_fd"))
343 extensions.push_back("VK_KHR_external_memory_fd");
345 if (context.isDeviceFunctionalitySupported("VK_EXT_external_memory_dma_buf"))
346 extensions.push_back("VK_EXT_external_memory_dma_buf");
348 if (context.isDeviceFunctionalitySupported("VK_KHR_external_semaphore_win32"))
349 extensions.push_back("VK_KHR_external_semaphore_win32");
350 if (context.isDeviceFunctionalitySupported("VK_KHR_external_memory_win32"))
351 extensions.push_back("VK_KHR_external_memory_win32");
353 if (context.isDeviceFunctionalitySupported("VK_KHR_timeline_semaphore"))
354 extensions.push_back("VK_KHR_timeline_semaphore");
358 std::vector<vk::VkDeviceQueueCreateInfo> queues;
360 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++)
362 const vk::VkDeviceQueueCreateInfo createInfo =
364 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
373 queues.push_back(createInfo);
376 const vk::VkPhysicalDeviceFeatures2 createPhysicalFeature =
378 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
380 context.getDeviceFeatures(),
382 const vk::VkDeviceCreateInfo createInfo =
384 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
385 &createPhysicalFeature,
388 (deUint32)queues.size(),
394 (deUint32)extensions.size(),
395 extensions.empty() ? DE_NULL : &extensions[0],
399 return vkt::createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &createInfo);
401 catch (const vk::Error& error)
403 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
404 TCU_THROW(NotSupportedError, "Required extensions not supported");
410 // Class to wrap a singleton instance and device
411 class InstanceAndDevice
413 InstanceAndDevice (Context& context)
414 : m_instance (createTestInstance(context))
415 , m_vki (m_instance.getDriver())
416 , m_physicalDevice (vk::chooseDevice(m_vki, m_instance, context.getTestContext().getCommandLine()))
417 , m_logicalDevice (createTestDevice(context, context.getPlatformInterface(), m_instance, m_vki, m_physicalDevice))
423 static vk::VkInstance getInstanceA(Context& context)
426 m_instanceA = SharedPtr<InstanceAndDevice>(new InstanceAndDevice(context));
428 return m_instanceA->m_instance;
430 static vk::VkInstance getInstanceB(Context& context)
433 m_instanceB = SharedPtr<InstanceAndDevice>(new InstanceAndDevice(context));
435 return m_instanceB->m_instance;
437 static const vk::InstanceDriver& getDriverA()
439 DE_ASSERT(m_instanceA);
440 return m_instanceA->m_instance.getDriver();
442 static const vk::InstanceDriver& getDriverB()
444 DE_ASSERT(m_instanceB);
445 return m_instanceB->m_instance.getDriver();
447 static vk::VkPhysicalDevice getPhysicalDeviceA()
449 DE_ASSERT(m_instanceA);
450 return m_instanceA->m_physicalDevice;
452 static vk::VkPhysicalDevice getPhysicalDeviceB()
454 DE_ASSERT(m_instanceB);
455 return m_instanceB->m_physicalDevice;
457 static const Unique<vk::VkDevice>& getDeviceA()
459 DE_ASSERT(m_instanceA);
460 return m_instanceA->m_logicalDevice;
462 static const Unique<vk::VkDevice>& getDeviceB()
464 DE_ASSERT(m_instanceB);
465 return m_instanceB->m_logicalDevice;
467 static void collectMessagesA()
469 DE_ASSERT(m_instanceA);
470 m_instanceA->m_instance.collectMessages();
472 static void collectMessagesB()
474 DE_ASSERT(m_instanceB);
475 m_instanceB->m_instance.collectMessages();
477 static void destroy()
484 CustomInstance m_instance;
485 const vk::InstanceDriver& m_vki;
486 const vk::VkPhysicalDevice m_physicalDevice;
487 const Unique<vk::VkDevice> m_logicalDevice;
489 static SharedPtr<InstanceAndDevice> m_instanceA;
490 static SharedPtr<InstanceAndDevice> m_instanceB;
492 SharedPtr<InstanceAndDevice> InstanceAndDevice::m_instanceA;
493 SharedPtr<InstanceAndDevice> InstanceAndDevice::m_instanceB;
496 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
497 const vk::VkDevice device,
498 deUint32 familyIndex)
502 vkd.getDeviceQueue(device, familyIndex, 0u, &queue);
507 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
509 deUint32 queueFamilyIndex)
511 const vk::VkCommandPoolCreateInfo createInfo =
513 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
520 return vk::createCommandPool(vkd, device, &createInfo);
523 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
525 vk::VkCommandPool commandPool)
527 const vk::VkCommandBufferLevel level = vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY;
528 const vk::VkCommandBufferAllocateInfo allocateInfo =
530 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
538 return vk::allocateCommandBuffer(vkd, device, &allocateInfo);
541 vk::VkMemoryRequirements getMemoryRequirements(const vk::DeviceInterface& vkd,
545 bool getMemReq2Supported)
547 vk::VkMemoryRequirements memoryRequirements = { 0u, 0u, 0u, };
549 if (getMemReq2Supported)
551 const vk::VkImageMemoryRequirementsInfo2 requirementInfo =
553 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
557 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
559 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
564 vk::VkMemoryRequirements2 requirements =
566 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
567 &dedicatedRequirements,
570 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
572 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
573 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation");
575 memoryRequirements = requirements.memoryRequirements;
579 vkd.getImageMemoryRequirements(device, image, &memoryRequirements);
582 return memoryRequirements;
585 vk::VkMemoryRequirements getMemoryRequirements(const vk::DeviceInterface& vkd,
589 bool getMemReq2Supported)
591 vk::VkMemoryRequirements memoryRequirements = { 0u, 0u, 0u, };
593 if (getMemReq2Supported)
595 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo =
597 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
601 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
603 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
608 vk::VkMemoryRequirements2 requirements =
610 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
611 &dedicatedRequirements,
614 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
616 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
617 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation");
619 memoryRequirements = requirements.memoryRequirements;
623 vkd.getBufferMemoryRequirements(device, buffer, &memoryRequirements);
626 return memoryRequirements;
629 Move<VkImage> createImage(const vk::DeviceInterface& vkd,
631 const ResourceDescription& resourceDesc,
632 const vk::VkExtent3D extent,
633 const std::vector<deUint32>& queueFamilyIndices,
634 const OperationSupport& readOp,
635 const OperationSupport& writeOp,
636 vk::VkExternalMemoryHandleTypeFlagBits externalType)
638 const vk::VkExternalMemoryImageCreateInfo externalInfo =
640 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
642 (vk::VkExternalMemoryHandleTypeFlags)externalType
644 const vk::VkImageCreateInfo createInfo =
646 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
650 resourceDesc.imageType,
651 resourceDesc.imageFormat,
655 vk::VK_SAMPLE_COUNT_1_BIT,
656 vk::VK_IMAGE_TILING_OPTIMAL,
657 readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
658 vk::VK_SHARING_MODE_EXCLUSIVE,
660 (deUint32)queueFamilyIndices.size(),
661 &queueFamilyIndices[0],
662 vk::VK_IMAGE_LAYOUT_UNDEFINED
665 return vk::createImage(vkd, device, &createInfo);
668 Move<VkBuffer> createBuffer(const vk::DeviceInterface& vkd,
670 const vk::VkDeviceSize size,
671 const vk::VkBufferUsageFlags usage,
672 const vk::VkExternalMemoryHandleTypeFlagBits memoryHandleType,
673 const std::vector<deUint32>& queueFamilyIndices)
675 const vk::VkExternalMemoryBufferCreateInfo externalInfo =
677 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
679 (vk::VkExternalMemoryHandleTypeFlags)memoryHandleType
681 const vk::VkBufferCreateInfo createInfo =
683 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
689 vk::VK_SHARING_MODE_EXCLUSIVE,
690 (deUint32)queueFamilyIndices.size(),
691 &queueFamilyIndices[0]
693 return vk::createBuffer(vkd, device, &createInfo);
696 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
699 NativeHandle& nativeHandle,
700 vk::VkExternalMemoryHandleTypeFlagBits externalType,
701 deUint32 exportedMemoryTypeIndex,
704 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vkd, device, buffer);
705 vk::Move<vk::VkDeviceMemory> memory = dedicated
706 ? importDedicatedMemory(vkd, device, buffer, requirements, externalType, exportedMemoryTypeIndex, nativeHandle)
707 : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle);
709 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
711 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
714 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
717 NativeHandle& nativeHandle,
718 vk::VkExternalMemoryHandleTypeFlagBits externalType,
719 deUint32 exportedMemoryTypeIndex,
722 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vkd, device, image);
723 vk::Move<vk::VkDeviceMemory> memory = dedicated
724 ? importDedicatedMemory(vkd, device, image, requirements, externalType, exportedMemoryTypeIndex, nativeHandle)
725 : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle);
726 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
728 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
731 de::MovePtr<Resource> importResource (const vk::DeviceInterface& vkd,
733 const ResourceDescription& resourceDesc,
734 const std::vector<deUint32>& queueFamilyIndices,
735 const OperationSupport& readOp,
736 const OperationSupport& writeOp,
737 NativeHandle& nativeHandle,
738 vk::VkExternalMemoryHandleTypeFlagBits externalType,
739 deUint32 exportedMemoryTypeIndex,
742 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
744 const vk::VkExtent3D extent =
746 (deUint32)resourceDesc.size.x(),
747 de::max(1u, (deUint32)resourceDesc.size.y()),
748 de::max(1u, (deUint32)resourceDesc.size.z())
750 const vk::VkImageSubresourceRange subresourceRange =
752 resourceDesc.imageAspect,
758 const vk::VkImageSubresourceLayers subresourceLayers =
760 resourceDesc.imageAspect,
765 const vk:: VkExternalMemoryImageCreateInfo externalInfo =
767 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
769 (vk::VkExternalMemoryHandleTypeFlags)externalType
771 const vk::VkImageCreateInfo createInfo =
773 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
777 resourceDesc.imageType,
778 resourceDesc.imageFormat,
782 vk::VK_SAMPLE_COUNT_1_BIT,
783 vk::VK_IMAGE_TILING_OPTIMAL,
784 readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags(),
785 vk::VK_SHARING_MODE_EXCLUSIVE,
787 (deUint32)queueFamilyIndices.size(),
788 &queueFamilyIndices[0],
789 vk::VK_IMAGE_LAYOUT_UNDEFINED
792 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
793 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *image, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
795 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
799 const vk::VkDeviceSize offset = 0u;
800 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
801 const vk::VkBufferUsageFlags usage = readOp.getInResourceUsageFlags() | writeOp.getOutResourceUsageFlags();
802 const vk:: VkExternalMemoryBufferCreateInfo externalInfo =
804 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
806 (vk::VkExternalMemoryHandleTypeFlags)externalType
808 const vk::VkBufferCreateInfo createInfo =
810 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
816 vk::VK_SHARING_MODE_EXCLUSIVE,
817 (deUint32)queueFamilyIndices.size(),
818 &queueFamilyIndices[0]
820 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
821 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
823 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
827 void recordWriteBarrier (const vk::DeviceInterface& vkd,
828 vk::VkCommandBuffer commandBuffer,
829 const Resource& resource,
830 const SyncInfo& writeSync,
831 deUint32 writeQueueFamilyIndex,
832 const SyncInfo& readSync)
834 const vk::VkPipelineStageFlags srcStageMask = writeSync.stageMask;
835 const vk::VkAccessFlags srcAccessMask = writeSync.accessMask;
837 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
838 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
840 const vk::VkDependencyFlags dependencyFlags = 0;
842 if (resource.getType() == RESOURCE_TYPE_IMAGE)
844 const vk::VkImageMemoryBarrier barrier =
846 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
852 writeSync.imageLayout,
853 readSync.imageLayout,
855 writeQueueFamilyIndex,
856 VK_QUEUE_FAMILY_EXTERNAL,
858 resource.getImage().handle,
859 resource.getImage().subresourceRange
862 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
866 const vk::VkBufferMemoryBarrier barrier =
868 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
874 writeQueueFamilyIndex,
875 VK_QUEUE_FAMILY_EXTERNAL,
877 resource.getBuffer().handle,
882 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
886 void recordReadBarrier (const vk::DeviceInterface& vkd,
887 vk::VkCommandBuffer commandBuffer,
888 const Resource& resource,
889 const SyncInfo& writeSync,
890 const SyncInfo& readSync,
891 deUint32 readQueueFamilyIndex)
893 const vk::VkPipelineStageFlags srcStageMask = readSync.stageMask;
894 const vk::VkAccessFlags srcAccessMask = readSync.accessMask;
896 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
897 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
899 const vk::VkDependencyFlags dependencyFlags = 0;
901 if (resource.getType() == RESOURCE_TYPE_IMAGE)
903 const vk::VkImageMemoryBarrier barrier =
905 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
911 writeSync.imageLayout,
912 readSync.imageLayout,
914 VK_QUEUE_FAMILY_EXTERNAL,
915 readQueueFamilyIndex,
917 resource.getImage().handle,
918 resource.getImage().subresourceRange
921 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
925 const vk::VkBufferMemoryBarrier barrier =
927 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
933 VK_QUEUE_FAMILY_EXTERNAL,
934 readQueueFamilyIndex,
936 resource.getBuffer().handle,
941 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
945 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
947 std::vector<deUint32> indices (properties.size(), 0);
949 for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
955 class SharingTestInstance : public TestInstance
958 SharingTestInstance (Context& context,
961 virtual tcu::TestStatus iterate (void);
964 const TestConfig m_config;
966 const de::UniquePtr<OperationSupport> m_supportWriteOp;
967 const de::UniquePtr<OperationSupport> m_supportReadOp;
968 const NotSupportedChecker m_notSupportedChecker; // Must declare before VkInstance to effectively reduce runtimes!
970 const bool m_getMemReq2Supported;
972 const vk::VkInstance m_instanceA;
973 const vk::InstanceDriver& m_vkiA;
974 const vk::VkPhysicalDevice m_physicalDeviceA;
975 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesA;
976 const std::vector<deUint32> m_queueFamilyIndicesA;
977 const vk::Unique<vk::VkDevice>& m_deviceA;
978 const vk::DeviceDriver m_vkdA;
980 const vk::VkInstance m_instanceB;
981 const vk::InstanceDriver& m_vkiB;
982 const vk::VkPhysicalDevice m_physicalDeviceB;
983 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesB;
984 const std::vector<deUint32> m_queueFamilyIndicesB;
985 const vk::Unique<vk::VkDevice>& m_deviceB;
986 const vk::DeviceDriver m_vkdB;
988 const vk::VkExternalSemaphoreHandleTypeFlagBits m_semaphoreHandleType;
989 const vk::VkExternalMemoryHandleTypeFlagBits m_memoryHandleType;
991 // \todo Should this be moved to the group same way as in the other tests?
992 PipelineCacheData m_pipelineCacheData;
993 tcu::ResultCollector m_resultCollector;
998 SharingTestInstance::SharingTestInstance (Context& context,
1000 : TestInstance (context)
1002 , m_supportWriteOp (makeOperationSupport(config.writeOp, config.resource))
1003 , m_supportReadOp (makeOperationSupport(config.readOp, config.resource))
1004 , m_notSupportedChecker (context, m_config, *m_supportWriteOp, *m_supportReadOp)
1005 , m_getMemReq2Supported (context.isDeviceFunctionalitySupported("VK_KHR_get_memory_requirements2"))
1007 , m_instanceA (InstanceAndDevice::getInstanceA(context))
1008 , m_vkiA (InstanceAndDevice::getDriverA())
1009 , m_physicalDeviceA (InstanceAndDevice::getPhysicalDeviceA())
1010 , m_queueFamiliesA (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiA, m_physicalDeviceA))
1011 , m_queueFamilyIndicesA (getFamilyIndices(m_queueFamiliesA))
1012 , m_deviceA (InstanceAndDevice::getDeviceA())
1013 , m_vkdA (context.getPlatformInterface(), m_instanceA, *m_deviceA)
1015 , m_instanceB (InstanceAndDevice::getInstanceB(context))
1016 , m_vkiB (InstanceAndDevice::getDriverB())
1017 , m_physicalDeviceB (InstanceAndDevice::getPhysicalDeviceB())
1018 , m_queueFamiliesB (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiB, m_physicalDeviceB))
1019 , m_queueFamilyIndicesB (getFamilyIndices(m_queueFamiliesB))
1020 , m_deviceB (InstanceAndDevice::getDeviceB())
1021 , m_vkdB (context.getPlatformInterface(), m_instanceB, *m_deviceB)
1023 , m_semaphoreHandleType (m_config.semaphoreHandleType)
1024 , m_memoryHandleType (m_config.memoryHandleType)
1026 , m_resultCollector (context.getTestContext().getLog())
1032 tcu::TestStatus SharingTestInstance::iterate (void)
1034 TestLog& log (m_context.getTestContext().getLog());
1038 const deUint32 queueFamilyA = (deUint32)m_queueANdx;
1039 const deUint32 queueFamilyB = (deUint32)m_queueBNdx;
1041 const tcu::ScopedLogSection queuePairSection (log,
1042 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB),
1043 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB));
1045 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphoreType(m_vkdA, *m_deviceA, m_config.semaphoreType, m_semaphoreHandleType));
1046 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphoreType(m_vkdB, *m_deviceB, m_config.semaphoreType));
1048 const ResourceDescription& resourceDesc = m_config.resource;
1049 de::MovePtr<Resource> resourceA;
1051 deUint32 exportedMemoryTypeIndex = ~0U;
1052 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
1054 const vk::VkExtent3D extent =
1056 (deUint32)resourceDesc.size.x(),
1057 de::max(1u, (deUint32)resourceDesc.size.y()),
1058 de::max(1u, (deUint32)resourceDesc.size.z())
1060 const vk::VkImageSubresourceRange subresourceRange =
1062 resourceDesc.imageAspect,
1068 const vk::VkImageSubresourceLayers subresourceLayers =
1070 resourceDesc.imageAspect,
1076 vk::Move<vk::VkImage> image = createImage(m_vkdA, *m_deviceA, resourceDesc, extent, m_queueFamilyIndicesA,
1077 *m_supportReadOp, *m_supportWriteOp, m_memoryHandleType);
1078 const vk::VkMemoryRequirements requirements = getMemoryRequirements(m_vkdA, *m_deviceA, *image, m_config.dedicated, m_getMemReq2Supported);
1079 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
1080 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(m_vkdA, *m_deviceA, requirements.size, exportedMemoryTypeIndex, m_memoryHandleType, m_config.dedicated ? *image : (vk::VkImage)0);
1082 VK_CHECK(m_vkdA.bindImageMemory(*m_deviceA, *image, *memory, 0u));
1084 de::MovePtr<vk::Allocation> allocation = de::MovePtr<vk::Allocation>(new SimpleAllocation(m_vkdA, *m_deviceA, memory.disown()));
1085 resourceA = de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
1089 const vk::VkDeviceSize offset = 0u;
1090 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
1091 const vk::VkBufferUsageFlags usage = m_supportReadOp->getInResourceUsageFlags() | m_supportWriteOp->getOutResourceUsageFlags();
1092 vk::Move<vk::VkBuffer> buffer = createBuffer(m_vkdA, *m_deviceA, size, usage, m_memoryHandleType, m_queueFamilyIndicesA);
1093 const vk::VkMemoryRequirements requirements = getMemoryRequirements(m_vkdA, *m_deviceA, *buffer, m_config.dedicated, m_getMemReq2Supported);
1094 exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits);
1095 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(m_vkdA, *m_deviceA, requirements.size, exportedMemoryTypeIndex, m_memoryHandleType, m_config.dedicated ? *buffer : (vk::VkBuffer)0);
1097 VK_CHECK(m_vkdA.bindBufferMemory(*m_deviceA, *buffer, *memory, 0u));
1099 de::MovePtr<vk::Allocation> allocation = de::MovePtr<vk::Allocation>(new SimpleAllocation(m_vkdA, *m_deviceA, memory.disown()));
1100 resourceA = de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
1103 NativeHandle nativeMemoryHandle;
1104 getMemoryNative(m_vkdA, *m_deviceA, resourceA->getMemory(), m_memoryHandleType, nativeMemoryHandle);
1106 const de::UniquePtr<Resource> resourceB (importResource(m_vkdB, *m_deviceB, resourceDesc, m_queueFamilyIndicesB, *m_supportReadOp, *m_supportWriteOp, nativeMemoryHandle, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated));
1109 const vk::VkQueue queueA (getQueue(m_vkdA, *m_deviceA, queueFamilyA));
1110 const vk::Unique<vk::VkCommandPool> commandPoolA (createCommandPool(m_vkdA, *m_deviceA, queueFamilyA));
1111 const vk::Unique<vk::VkCommandBuffer> commandBufferA (createCommandBuffer(m_vkdA, *m_deviceA, *commandPoolA));
1112 vk::SimpleAllocator allocatorA (m_vkdA, *m_deviceA, vk::getPhysicalDeviceMemoryProperties(m_vkiA, m_physicalDeviceA));
1113 OperationContext operationContextA (m_context, m_vkiA, m_vkdA, m_physicalDeviceA, *m_deviceA, allocatorA, m_context.getBinaryCollection(), m_pipelineCacheData);
1115 if (!checkQueueFlags(m_queueFamiliesA[m_queueANdx].queueFlags , m_supportWriteOp->getQueueFlags(operationContextA)))
1116 TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
1118 const vk::VkQueue queueB (getQueue(m_vkdB, *m_deviceB, queueFamilyB));
1119 const vk::Unique<vk::VkCommandPool> commandPoolB (createCommandPool(m_vkdB, *m_deviceB, queueFamilyB));
1120 const vk::Unique<vk::VkCommandBuffer> commandBufferB (createCommandBuffer(m_vkdB, *m_deviceB, *commandPoolB));
1121 vk::SimpleAllocator allocatorB (m_vkdB, *m_deviceB, vk::getPhysicalDeviceMemoryProperties(m_vkiB, m_physicalDeviceB));
1122 OperationContext operationContextB (m_context, m_vkiB, m_vkdB, m_physicalDeviceB, *m_deviceB, allocatorB, m_context.getBinaryCollection(), m_pipelineCacheData);
1124 if (!checkQueueFlags(m_queueFamiliesB[m_queueBNdx].queueFlags , m_supportReadOp->getQueueFlags(operationContextB)))
1125 TCU_THROW(NotSupportedError, "Operation not supported by the destination queue");
1127 const de::UniquePtr<Operation> writeOp (m_supportWriteOp->build(operationContextA, *resourceA));
1128 const de::UniquePtr<Operation> readOp (m_supportReadOp->build(operationContextB, *resourceB));
1130 const SyncInfo writeSync = writeOp->getOutSyncInfo();
1131 const SyncInfo readSync = readOp->getInSyncInfo();
1133 beginCommandBuffer(m_vkdA, *commandBufferA);
1134 writeOp->recordCommands(*commandBufferA);
1135 recordWriteBarrier(m_vkdA, *commandBufferA, *resourceA, writeSync, queueFamilyA, readSync);
1136 endCommandBuffer(m_vkdA, *commandBufferA);
1138 beginCommandBuffer(m_vkdB, *commandBufferB);
1139 recordReadBarrier(m_vkdB, *commandBufferB, *resourceB, writeSync, readSync, queueFamilyB);
1140 readOp->recordCommands(*commandBufferB);
1141 endCommandBuffer(m_vkdB, *commandBufferB);
1144 de::Random rng (1234);
1145 const deUint64 timelineValue = rng.getInt(1, deIntMaxValue32(32));
1146 const vk::VkCommandBuffer commandBuffer = *commandBufferA;
1147 const vk::VkSemaphore semaphore = *semaphoreA;
1148 const vk::VkTimelineSemaphoreSubmitInfo semaphoreSubmitInfo =
1150 vk::VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, // VkStructureType sType;
1151 DE_NULL, // const void* pNext;
1152 0u, // deUint32 waitSemaphoreValueCount
1153 DE_NULL, // const deUint64* pWaitSemaphoreValues
1154 1u, // deUint32 signalSemaphoreValueCount
1155 &timelineValue, // const deUint64* pSignalSemaphoreValues
1157 const vk::VkSubmitInfo submitInfo =
1159 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1160 m_config.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE_KHR ? &semaphoreSubmitInfo : DE_NULL,
1170 VK_CHECK(m_vkdA.queueSubmit(queueA, 1u, &submitInfo, DE_NULL));
1173 NativeHandle nativeSemaphoreHandle;
1175 getSemaphoreNative(m_vkdA, *m_deviceA, *semaphoreA, m_semaphoreHandleType, nativeSemaphoreHandle);
1176 importSemaphore(m_vkdB, *m_deviceB, *semaphoreB, m_semaphoreHandleType, nativeSemaphoreHandle, 0u);
1180 const deUint64 timelineValue = 1u;
1181 const vk::VkCommandBuffer commandBuffer = *commandBufferB;
1182 const vk::VkSemaphore semaphore = *semaphoreB;
1183 const vk::VkPipelineStageFlags dstStage = readSync.stageMask;
1184 const vk::VkTimelineSemaphoreSubmitInfo semaphoreSubmitInfo =
1186 vk::VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, // VkStructureType sType;
1187 DE_NULL, // const void* pNext;
1188 1u, // deUint32 waitSemaphoreValueCount
1189 &timelineValue, // const deUint64* pWaitSemaphoreValues
1190 0u, // deUint32 signalSemaphoreValueCount
1191 DE_NULL, // const deUint64* pSignalSemaphoreValues
1193 const vk::VkSubmitInfo submitInfo =
1195 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1196 m_config.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE_KHR ? &semaphoreSubmitInfo : DE_NULL,
1208 VK_CHECK(m_vkdB.queueSubmit(queueB, 1u, &submitInfo, DE_NULL));
1211 VK_CHECK(m_vkdA.queueWaitIdle(queueA));
1212 VK_CHECK(m_vkdB.queueWaitIdle(queueB));
1214 if (m_config.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE_KHR)
1219 VK_CHECK(m_vkdA.getSemaphoreCounterValue(*m_deviceA, *semaphoreA, &valueA));
1220 VK_CHECK(m_vkdB.getSemaphoreCounterValue(*m_deviceB, *semaphoreB, &valueB));
1222 if (valueA != valueB)
1223 return tcu::TestStatus::fail("Inconsistent values between shared semaphores");
1227 const Data expected = writeOp->getData();
1228 const Data actual = readOp->getData();
1230 DE_ASSERT(expected.size == actual.size);
1232 if (!isIndirectBuffer(m_config.resource.type))
1234 if (0 != deMemCmp(expected.data, actual.data, expected.size))
1236 const size_t maxBytesLogged = 256;
1237 std::ostringstream expectedData;
1238 std::ostringstream actualData;
1241 // Find first byte difference
1242 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1247 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1249 // Log 8 previous bytes before the first incorrect byte
1252 expectedData << "... ";
1253 actualData << "... ";
1260 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1262 expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1263 actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1266 if (expected.size > byteNdx)
1268 expectedData << "...";
1269 actualData << "...";
1272 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1273 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1275 m_resultCollector.fail("Memory contents don't match");
1280 const deUint32 expectedValue = reinterpret_cast<const deUint32*>(expected.data)[0];
1281 const deUint32 actualValue = reinterpret_cast<const deUint32*>(actual.data)[0];
1283 if (actualValue < expectedValue)
1285 log << TestLog::Message << "Expected counter value: (" << expectedValue << ")" << TestLog::EndMessage;
1286 log << TestLog::Message << "Actual counter value: (" << actualValue << ")" << TestLog::EndMessage;
1288 m_resultCollector.fail("Counter value is smaller than expected");
1293 catch (const tcu::NotSupportedError& error)
1295 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1297 catch (const tcu::TestError& error)
1299 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1302 // Collect possible validation errors.
1303 InstanceAndDevice::collectMessagesA();
1304 InstanceAndDevice::collectMessagesB();
1306 // Move to next queue
1310 if (m_queueBNdx >= m_queueFamiliesB.size())
1314 if (m_queueANdx >= m_queueFamiliesA.size())
1316 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1322 return tcu::TestStatus::incomplete();
1326 return tcu::TestStatus::incomplete();
1332 void init (vk::SourceCollections& dst, TestConfig config) const
1334 const de::UniquePtr<OperationSupport> readOp (makeOperationSupport(config.readOp, config.resource));
1335 const de::UniquePtr<OperationSupport> writeOp (makeOperationSupport(config.writeOp, config.resource));
1337 readOp->initPrograms(dst);
1338 writeOp->initPrograms(dst);
1344 static void createTests (tcu::TestCaseGroup* group)
1346 tcu::TestContext& testCtx = group->getTestContext();
1349 vk::VkExternalMemoryHandleTypeFlagBits memoryType;
1350 vk::VkExternalSemaphoreHandleTypeFlagBits semaphoreType;
1351 const char* nameSuffix;
1355 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
1356 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
1360 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
1361 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
1365 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
1366 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
1370 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT,
1371 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT,
1375 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
1376 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
1381 const std::string semaphoreNames[vk::VK_SEMAPHORE_TYPE_LAST] =
1383 "_binary_semaphore",
1384 "_timeline_semaphore",
1387 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
1389 const bool dedicated (dedicatedNdx == 1);
1390 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
1392 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
1393 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
1395 const OperationName writeOp = s_writeOps[writeOpNdx];
1396 const OperationName readOp = s_readOps[readOpNdx];
1397 const std::string opGroupName = getOperationName(writeOp) + "_" + getOperationName(readOp);
1400 de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1402 for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resources); ++resourceNdx)
1404 const ResourceDescription& resource = s_resources[resourceNdx];
1406 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1408 for (int semaphoreType = 0; semaphoreType < vk::VK_SEMAPHORE_TYPE_LAST; semaphoreType++)
1410 if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1412 const TestConfig config (resource, (vk::VkSemaphoreType)semaphoreType, writeOp, readOp, cases[caseNdx].memoryType, cases[caseNdx].semaphoreType, dedicated);
1413 std::string name = getResourceName(resource) + semaphoreNames[semaphoreType] + cases[caseNdx].nameSuffix;
1415 opGroup->addChild(new InstanceFactory1<SharingTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, "", Progs(), config));
1423 dedicatedGroup->addChild(opGroup.release());
1426 group->addChild(dedicatedGroup.release());
1430 static void cleanupGroup (tcu::TestCaseGroup* group)
1433 // Destroy singleton object
1434 InstanceAndDevice::destroy();
1437 tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
1439 return createTestGroup(testCtx, "cross_instance", "", createTests, cleanupGroup);
1442 } // synchronization