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"
29 #include "vktTestCaseUtil.hpp"
31 #include "vktSynchronizationUtil.hpp"
32 #include "vktSynchronizationOperation.hpp"
33 #include "vktSynchronizationOperationTestData.hpp"
34 #include "vktExternalMemoryUtil.hpp"
36 #include "tcuResultCollector.hpp"
37 #include "tcuTestLog.hpp"
40 using namespace vkt::ExternalMemoryUtil;
44 namespace synchronization
51 TestConfig (const ResourceDescription& resource_,
52 OperationName writeOp_,
53 OperationName readOp_,
54 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType_,
55 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreHandleType_,
57 : resource (resource_)
60 , memoryHandleType (memoryHandleType_)
61 , semaphoreHandleType (semaphoreHandleType_)
62 , dedicated (dedicated_)
66 const ResourceDescription resource;
67 const OperationName writeOp;
68 const OperationName readOp;
69 const vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType;
70 const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreHandleType;
74 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
76 if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
77 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT;
79 return (availableFlags & neededFlags) != 0;
82 class SimpleAllocation : public vk::Allocation
85 SimpleAllocation (const vk::DeviceInterface& vkd,
87 const vk::VkDeviceMemory memory);
88 ~SimpleAllocation (void);
91 const vk::DeviceInterface& m_vkd;
92 const vk::VkDevice m_device;
95 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface& vkd,
97 const vk::VkDeviceMemory memory)
98 : Allocation (memory, 0, DE_NULL)
104 SimpleAllocation::~SimpleAllocation (void)
106 m_vkd.freeMemory(m_device, getMemory(), DE_NULL);
112 DeviceId (deUint32 vendorId,
113 deUint32 driverVersion,
114 const deUint8 driverUUID[VK_UUID_SIZE],
115 const deUint8 deviceUUID[VK_UUID_SIZE]);
117 bool operator== (const DeviceId& other) const;
118 bool operator|= (const DeviceId& other) const;
121 const deUint32 m_vendorId;
122 const deUint32 m_driverVersion;
123 deUint8 m_driverUUID[VK_UUID_SIZE];
124 deUint8 m_deviceUUID[VK_UUID_SIZE];
127 DeviceId::DeviceId (deUint32 vendorId,
128 deUint32 driverVersion,
129 const deUint8 driverUUID[VK_UUID_SIZE],
130 const deUint8 deviceUUID[VK_UUID_SIZE])
131 : m_vendorId (vendorId)
132 , m_driverVersion (driverVersion)
134 deMemcpy(m_driverUUID, driverUUID, sizeof(m_driverUUID));
135 deMemcpy(m_deviceUUID, deviceUUID, sizeof(m_deviceUUID));
138 bool DeviceId::operator== (const DeviceId& other) const
143 if (m_vendorId != other.m_vendorId)
146 if (m_driverVersion != other.m_driverVersion)
149 if (deMemCmp(m_driverUUID, other.m_driverUUID, sizeof(m_driverUUID)) != 0)
152 return deMemCmp(m_deviceUUID, other.m_deviceUUID, sizeof(m_deviceUUID)) == 0;
155 DeviceId getDeviceId (const vk::InstanceInterface& vki,
156 vk::VkPhysicalDevice physicalDevice)
158 vk::VkPhysicalDeviceIDPropertiesKHR propertiesId;
159 vk::VkPhysicalDeviceProperties2KHR properties;
161 deMemset(&properties, 0, sizeof(properties));
162 deMemset(&propertiesId, 0, sizeof(propertiesId));
164 propertiesId.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
166 properties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
167 properties.pNext = &propertiesId;
169 vki.getPhysicalDeviceProperties2KHR(physicalDevice, &properties);
171 return DeviceId(properties.properties.vendorID, properties.properties.driverVersion, propertiesId.driverUUID, propertiesId.deviceUUID);
174 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp)
178 std::vector<std::string> extensions;
180 extensions.push_back("VK_KHR_get_physical_device_properties2");
182 extensions.push_back("VK_KHR_external_semaphore_capabilities");
183 extensions.push_back("VK_KHR_external_memory_capabilities");
185 return vk::createDefaultInstance(vkp, std::vector<std::string>(), extensions);
187 catch (const vk::Error& error)
189 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
190 TCU_THROW(NotSupportedError, "Required external memory extensions not supported by the instance");
196 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki,
197 vk::VkInstance instance,
198 const tcu::CommandLine& cmdLine)
200 return vk::chooseDevice(vki, instance, cmdLine);
203 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki, vk::VkInstance instance, const DeviceId& deviceId)
205 const std::vector<vk::VkPhysicalDevice> devices (vk::enumeratePhysicalDevices(vki, instance));
207 for (size_t deviceNdx = 0; deviceNdx < devices.size(); deviceNdx++)
209 if (deviceId == getDeviceId(vki, devices[deviceNdx]))
210 return devices[deviceNdx];
213 TCU_FAIL("No matching device found");
215 return (vk::VkPhysicalDevice)0;
218 vk::Move<vk::VkDevice> createDevice (const vk::InstanceInterface& vki,
219 vk::VkPhysicalDevice physicalDevice,
220 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType,
221 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreHandleType,
224 const float priority = 0.0f;
225 const std::vector<vk::VkQueueFamilyProperties> queueFamilyProperties = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
226 std::vector<deUint32> queueFamilyIndices (queueFamilyProperties.size(), 0xFFFFFFFFu);
227 std::vector<const char*> extensions;
230 extensions.push_back("VK_KHR_dedicated_allocation");
232 extensions.push_back("VK_KHR_get_memory_requirements2");
233 extensions.push_back("VK_KHR_external_semaphore");
234 extensions.push_back("VK_KHR_external_memory");
236 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
237 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
238 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
240 extensions.push_back("VK_KHR_external_semaphore_fd");
241 extensions.push_back("VK_KHR_external_memory_fd");
244 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
245 || memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR
246 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
247 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
249 extensions.push_back("VK_KHR_external_semaphore_win32");
250 extensions.push_back("VK_KHR_external_memory_win32");
255 std::vector<vk::VkDeviceQueueCreateInfo> queues;
257 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++)
259 const vk::VkDeviceQueueCreateInfo createInfo =
261 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
270 queues.push_back(createInfo);
273 const vk::VkDeviceCreateInfo createInfo =
275 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
279 (deUint32)queues.size(),
285 (deUint32)extensions.size(),
286 extensions.empty() ? DE_NULL : &extensions[0],
290 return vk::createDevice(vki, physicalDevice, &createInfo);
292 catch (const vk::Error& error)
294 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
295 TCU_THROW(NotSupportedError, "Required extensions not supported");
301 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
302 const vk::VkDevice device,
303 deUint32 familyIndex)
307 vkd.getDeviceQueue(device, familyIndex, 0u, &queue);
312 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
314 deUint32 queueFamilyIndex)
316 const vk::VkCommandPoolCreateInfo createInfo =
318 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
325 return vk::createCommandPool(vkd, device, &createInfo);
328 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
330 vk::VkCommandPool commandPool)
332 const vk::VkCommandBufferLevel level = vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY;
333 const vk::VkCommandBufferAllocateInfo allocateInfo =
335 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
343 return vk::allocateCommandBuffer(vkd, device, &allocateInfo);
346 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface& vkd,
349 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
352 const vk::VkBufferMemoryRequirementsInfo2KHR requirementInfo =
354 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
358 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
360 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
365 vk::VkMemoryRequirements2KHR requirements =
367 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
368 &dedicatedRequirements,
371 vkd.getBufferMemoryRequirements2KHR(device, &requirementInfo, &requirements);
373 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
374 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation");
376 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, requirements.memoryRequirements, externalType, dedicated ? buffer : (vk::VkBuffer)0);
377 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
379 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
382 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface& vkd,
385 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
388 const vk::VkImageMemoryRequirementsInfo2KHR requirementInfo =
390 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
394 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
396 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
401 vk::VkMemoryRequirements2KHR requirements =
403 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
404 &dedicatedRequirements,
407 vkd.getImageMemoryRequirements2KHR(device, &requirementInfo, &requirements);
409 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
410 TCU_THROW(NotSupportedError, "Memomry requires dedicated allocation");
412 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, requirements.memoryRequirements, externalType, dedicated ? image : (vk::VkImage)0);
413 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
415 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
418 de::MovePtr<Resource> createResource (const vk::DeviceInterface& vkd,
420 const ResourceDescription& resourceDesc,
421 const std::vector<deUint32>& queueFamilyIndices,
422 const OperationSupport& readOp,
423 const OperationSupport& writeOp,
424 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
427 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
429 const vk::VkExtent3D extent =
431 (deUint32)resourceDesc.size.x(),
432 de::max(1u, (deUint32)resourceDesc.size.y()),
433 de::max(1u, (deUint32)resourceDesc.size.z())
435 const vk::VkImageSubresourceRange subresourceRange =
437 resourceDesc.imageAspect,
443 const vk::VkImageSubresourceLayers subresourceLayers =
445 resourceDesc.imageAspect,
450 const vk::VkExternalMemoryImageCreateInfoKHR externalInfo =
452 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
454 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
456 const vk::VkImageCreateInfo createInfo =
458 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
462 resourceDesc.imageType,
463 resourceDesc.imageFormat,
467 vk::VK_SAMPLE_COUNT_1_BIT,
468 vk::VK_IMAGE_TILING_OPTIMAL,
469 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
470 vk::VK_SHARING_MODE_EXCLUSIVE,
472 (deUint32)queueFamilyIndices.size(),
473 &queueFamilyIndices[0],
474 vk::VK_IMAGE_LAYOUT_UNDEFINED
477 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
478 de::MovePtr<vk::Allocation> allocation = allocateAndBindMemory(vkd, device, *image, externalType, dedicated);
480 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
484 const vk::VkDeviceSize offset = 0u;
485 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
486 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
487 const vk:: VkExternalMemoryBufferCreateInfoKHR externalInfo =
489 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
491 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
493 const vk::VkBufferCreateInfo createInfo =
495 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
501 vk::VK_SHARING_MODE_EXCLUSIVE,
502 (deUint32)queueFamilyIndices.size(),
503 &queueFamilyIndices[0]
505 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
506 de::MovePtr<vk::Allocation> allocation = allocateAndBindMemory(vkd, device, *buffer, externalType, dedicated);
508 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
512 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
515 NativeHandle& nativeHandle,
516 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
519 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vkd, device, buffer);
520 vk::Move<vk::VkDeviceMemory> memory = dedicated
521 ? importDedicatedMemory(vkd, device, buffer, requirements, externalType, nativeHandle)
522 : importMemory(vkd, device, requirements, externalType, nativeHandle);
524 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
526 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
529 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
532 NativeHandle& nativeHandle,
533 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
536 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vkd, device, image);
537 vk::Move<vk::VkDeviceMemory> memory = dedicated
538 ? importDedicatedMemory(vkd, device, image, requirements, externalType, nativeHandle)
539 : importMemory(vkd, device, requirements, externalType, nativeHandle);
540 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
542 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
545 de::MovePtr<Resource> importResource (const vk::DeviceInterface& vkd,
547 const ResourceDescription& resourceDesc,
548 const std::vector<deUint32>& queueFamilyIndices,
549 const OperationSupport& readOp,
550 const OperationSupport& writeOp,
551 NativeHandle& nativeHandle,
552 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
555 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
557 const vk::VkExtent3D extent =
559 (deUint32)resourceDesc.size.x(),
560 de::max(1u, (deUint32)resourceDesc.size.y()),
561 de::max(1u, (deUint32)resourceDesc.size.z())
563 const vk::VkImageSubresourceRange subresourceRange =
565 resourceDesc.imageAspect,
571 const vk::VkImageSubresourceLayers subresourceLayers =
573 resourceDesc.imageAspect,
578 const vk:: VkExternalMemoryImageCreateInfoKHR externalInfo =
580 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
582 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
584 const vk::VkImageCreateInfo createInfo =
586 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
590 resourceDesc.imageType,
591 resourceDesc.imageFormat,
595 vk::VK_SAMPLE_COUNT_1_BIT,
596 vk::VK_IMAGE_TILING_OPTIMAL,
597 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
598 vk::VK_SHARING_MODE_EXCLUSIVE,
600 (deUint32)queueFamilyIndices.size(),
601 &queueFamilyIndices[0],
602 vk::VK_IMAGE_LAYOUT_UNDEFINED
605 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
606 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *image, nativeHandle, externalType, dedicated);
608 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
612 const vk::VkDeviceSize offset = 0u;
613 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
614 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
615 const vk:: VkExternalMemoryBufferCreateInfoKHR externalInfo =
617 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
619 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
621 const vk::VkBufferCreateInfo createInfo =
623 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
629 vk::VK_SHARING_MODE_EXCLUSIVE,
630 (deUint32)queueFamilyIndices.size(),
631 &queueFamilyIndices[0]
633 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
634 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType, dedicated);
636 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
640 void recordWriteBarrier (const vk::DeviceInterface& vkd,
641 vk::VkCommandBuffer commandBuffer,
642 const Resource& resource,
643 const SyncInfo& writeSync,
644 deUint32 writeQueueFamilyIndex,
645 const SyncInfo& readSync)
647 const vk::VkPipelineStageFlags srcStageMask = writeSync.stageMask;
648 const vk::VkAccessFlags srcAccessMask = writeSync.accessMask;
650 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
651 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
653 const vk::VkDependencyFlags dependencyFlags = 0;
655 if (resource.getType() == RESOURCE_TYPE_IMAGE)
657 const vk::VkImageMemoryBarrier barrier =
659 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
665 writeSync.imageLayout,
666 readSync.imageLayout,
668 writeQueueFamilyIndex,
669 VK_QUEUE_FAMILY_EXTERNAL_KHR,
671 resource.getImage().handle,
672 resource.getImage().subresourceRange
675 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
679 const vk::VkBufferMemoryBarrier barrier =
681 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
687 writeQueueFamilyIndex,
688 VK_QUEUE_FAMILY_EXTERNAL_KHR,
690 resource.getBuffer().handle,
695 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
699 void recordReadBarrier (const vk::DeviceInterface& vkd,
700 vk::VkCommandBuffer commandBuffer,
701 const Resource& resource,
702 const SyncInfo& writeSync,
703 const SyncInfo& readSync,
704 deUint32 readQueueFamilyIndex)
706 const vk::VkPipelineStageFlags srcStageMask = readSync.stageMask;
707 const vk::VkAccessFlags srcAccessMask = readSync.accessMask;
709 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
710 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
712 const vk::VkDependencyFlags dependencyFlags = 0;
714 if (resource.getType() == RESOURCE_TYPE_IMAGE)
716 const vk::VkImageMemoryBarrier barrier =
718 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
724 writeSync.imageLayout,
725 readSync.imageLayout,
727 VK_QUEUE_FAMILY_EXTERNAL_KHR,
728 readQueueFamilyIndex,
730 resource.getImage().handle,
731 resource.getImage().subresourceRange
734 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
738 const vk::VkBufferMemoryBarrier barrier =
740 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
746 VK_QUEUE_FAMILY_EXTERNAL_KHR,
747 readQueueFamilyIndex,
749 resource.getBuffer().handle,
754 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
758 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
760 std::vector<deUint32> indices (properties.size(), 0);
762 for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
768 class SharingTestInstance : public TestInstance
771 SharingTestInstance (Context& context,
774 virtual tcu::TestStatus iterate (void);
777 const TestConfig m_config;
778 const de::UniquePtr<OperationSupport> m_supportWriteOp;
779 const de::UniquePtr<OperationSupport> m_supportReadOp;
781 const vk::Unique<vk::VkInstance> m_instanceA;
783 const vk::InstanceDriver m_vkiA;
784 const vk::VkPhysicalDevice m_physicalDeviceA;
785 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesA;
786 const std::vector<deUint32> m_queueFamilyIndicesA;
788 const vk::Unique<vk::VkDevice> m_deviceA;
789 const vk::DeviceDriver m_vkdA;
791 const vk::Unique<vk::VkInstance> m_instanceB;
792 const vk::InstanceDriver m_vkiB;
793 const vk::VkPhysicalDevice m_physicalDeviceB;
794 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesB;
795 const std::vector<deUint32> m_queueFamilyIndicesB;
796 const vk::Unique<vk::VkDevice> m_deviceB;
797 const vk::DeviceDriver m_vkdB;
799 const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR m_semaphoreHandleType;
800 const vk::VkExternalMemoryHandleTypeFlagBitsKHR m_memoryHandleType;
802 // \todo Should this be moved to the group same way as in the other tests?
803 PipelineCacheData m_pipelineCacheData;
804 tcu::ResultCollector m_resultCollector;
809 SharingTestInstance::SharingTestInstance (Context& context,
811 : TestInstance (context)
813 , m_supportWriteOp (makeOperationSupport(config.writeOp, config.resource))
814 , m_supportReadOp (makeOperationSupport(config.readOp, config.resource))
816 , m_instanceA (createInstance(context.getPlatformInterface()))
818 , m_vkiA (context.getPlatformInterface(), *m_instanceA)
819 , m_physicalDeviceA (getPhysicalDevice(m_vkiA, *m_instanceA, context.getTestContext().getCommandLine()))
820 , m_queueFamiliesA (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiA, m_physicalDeviceA))
821 , m_queueFamilyIndicesA (getFamilyIndices(m_queueFamiliesA))
822 , m_deviceA (createDevice(m_vkiA, m_physicalDeviceA, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated))
823 , m_vkdA (m_vkiA, *m_deviceA)
825 , m_instanceB (createInstance(context.getPlatformInterface()))
827 , m_vkiB (context.getPlatformInterface(), *m_instanceB)
828 , m_physicalDeviceB (getPhysicalDevice(m_vkiB, *m_instanceB, getDeviceId(m_vkiA, m_physicalDeviceA)))
829 , m_queueFamiliesB (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiB, m_physicalDeviceB))
830 , m_queueFamilyIndicesB (getFamilyIndices(m_queueFamiliesB))
831 , m_deviceB (createDevice(m_vkiB, m_physicalDeviceB, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated))
832 , m_vkdB (m_vkiB, *m_deviceB)
834 , m_semaphoreHandleType (m_config.semaphoreHandleType)
835 , m_memoryHandleType (m_config.memoryHandleType)
837 , m_resultCollector (context.getTestContext().getLog())
841 TestLog& log = m_context.getTestContext().getLog();
843 // Check resource support
844 if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
846 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR externalInfo =
848 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
852 const vk::VkPhysicalDeviceImageFormatInfo2KHR imageFormatInfo =
854 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
856 m_config.resource.imageFormat,
857 m_config.resource.imageType,
858 vk::VK_IMAGE_TILING_OPTIMAL,
859 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
862 vk::VkExternalImageFormatPropertiesKHR externalProperties =
864 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
868 vk::VkImageFormatProperties2KHR formatProperties =
870 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
882 const vk::VkResult res = m_vkiA.getPhysicalDeviceImageFormatProperties2KHR(m_physicalDeviceA, &imageFormatInfo, &formatProperties);
884 if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
885 TCU_THROW(NotSupportedError, "Image format not supported");
887 VK_CHECK(res); // Check other errors
890 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
892 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
893 TCU_THROW(NotSupportedError, "Exporting image resource not supported");
895 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
896 TCU_THROW(NotSupportedError, "Importing image resource not supported");
900 const vk::VkPhysicalDeviceExternalBufferInfoKHR info =
902 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
906 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
909 vk::VkExternalBufferPropertiesKHR properties =
911 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
915 m_vkiA.getPhysicalDeviceExternalBufferPropertiesKHR(m_physicalDeviceA, &info, &properties);
917 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
919 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0
920 || (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
921 TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported");
924 // Check semaphore support
926 const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR info =
928 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
930 m_semaphoreHandleType
932 vk::VkExternalSemaphorePropertiesKHR properties;
934 m_vkiA.getPhysicalDeviceExternalSemaphorePropertiesKHR(m_physicalDeviceA, &info, &properties);
936 log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
938 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0
939 || (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
940 TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported");
944 tcu::TestStatus SharingTestInstance::iterate (void)
946 TestLog& log (m_context.getTestContext().getLog());
948 const deUint32 queueFamilyA = (deUint32)m_queueANdx;
949 const deUint32 queueFamilyB = (deUint32)m_queueBNdx;
951 const tcu::ScopedLogSection queuePairSection (log,
952 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB),
953 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB));
955 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(m_vkdA, *m_deviceA, m_semaphoreHandleType));
956 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(m_vkdB, *m_deviceB));
958 const de::UniquePtr<Resource> resourceA (createResource(m_vkdA, *m_deviceA, m_config.resource, m_queueFamilyIndicesA, *m_supportReadOp, *m_supportWriteOp, m_memoryHandleType, m_config.dedicated));
960 NativeHandle nativeMemoryHandle;
961 getMemoryNative(m_vkdA, *m_deviceA, resourceA->getMemory(), m_memoryHandleType, nativeMemoryHandle);
963 const de::UniquePtr<Resource> resourceB (importResource(m_vkdB, *m_deviceB, m_config.resource, m_queueFamilyIndicesB, *m_supportReadOp, *m_supportWriteOp, nativeMemoryHandle, m_memoryHandleType, m_config.dedicated));
967 const vk::VkQueue queueA (getQueue(m_vkdA, *m_deviceA, queueFamilyA));
968 const vk::Unique<vk::VkCommandPool> commandPoolA (createCommandPool(m_vkdA, *m_deviceA, queueFamilyA));
969 const vk::Unique<vk::VkCommandBuffer> commandBufferA (createCommandBuffer(m_vkdA, *m_deviceA, *commandPoolA));
970 vk::SimpleAllocator allocatorA (m_vkdA, *m_deviceA, vk::getPhysicalDeviceMemoryProperties(m_vkiA, m_physicalDeviceA));
971 const std::vector<std::string> deviceExtensionsA;
972 OperationContext operationContextA (m_vkiA, m_vkdA, m_physicalDeviceA, *m_deviceA, allocatorA, deviceExtensionsA, m_context.getBinaryCollection(), m_pipelineCacheData);
974 if (!checkQueueFlags(m_queueFamiliesA[m_queueANdx].queueFlags , m_supportWriteOp->getQueueFlags(operationContextA)))
975 TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
977 const vk::VkQueue queueB (getQueue(m_vkdB, *m_deviceB, queueFamilyB));
978 const vk::Unique<vk::VkCommandPool> commandPoolB (createCommandPool(m_vkdB, *m_deviceB, queueFamilyB));
979 const vk::Unique<vk::VkCommandBuffer> commandBufferB (createCommandBuffer(m_vkdB, *m_deviceB, *commandPoolB));
980 vk::SimpleAllocator allocatorB (m_vkdB, *m_deviceB, vk::getPhysicalDeviceMemoryProperties(m_vkiB, m_physicalDeviceB));
981 const std::vector<std::string> deviceExtensionsB;
982 OperationContext operationContextB (m_vkiB, m_vkdB, m_physicalDeviceB, *m_deviceB, allocatorB, deviceExtensionsB, m_context.getBinaryCollection(), m_pipelineCacheData);
984 if (!checkQueueFlags(m_queueFamiliesB[m_queueBNdx].queueFlags , m_supportReadOp->getQueueFlags(operationContextB)))
985 TCU_THROW(NotSupportedError, "Operation not supported by the destination queue");
987 const de::UniquePtr<Operation> writeOp (m_supportWriteOp->build(operationContextA, *resourceA));
988 const de::UniquePtr<Operation> readOp (m_supportReadOp->build(operationContextB, *resourceB));
990 const SyncInfo writeSync = writeOp->getSyncInfo();
991 const SyncInfo readSync = readOp->getSyncInfo();
993 beginCommandBuffer(m_vkdA, *commandBufferA);
994 writeOp->recordCommands(*commandBufferA);
995 recordWriteBarrier(m_vkdA, *commandBufferA, *resourceA, writeSync, queueFamilyA, readSync);
996 endCommandBuffer(m_vkdA, *commandBufferA);
998 beginCommandBuffer(m_vkdB, *commandBufferB);
999 recordReadBarrier(m_vkdB, *commandBufferB, *resourceB, writeSync, readSync, queueFamilyB);
1000 readOp->recordCommands(*commandBufferB);
1001 endCommandBuffer(m_vkdB, *commandBufferB);
1004 const vk::VkCommandBuffer commandBuffer = *commandBufferA;
1005 const vk::VkSemaphore semaphore = *semaphoreA;
1006 const vk::VkSubmitInfo submitInfo =
1008 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1021 VK_CHECK(m_vkdA.queueSubmit(queueA, 1u, &submitInfo, DE_NULL));
1024 NativeHandle nativeSemaphoreHandle;
1026 getSemaphoreNative(m_vkdA, *m_deviceA, *semaphoreA, m_semaphoreHandleType, nativeSemaphoreHandle);
1027 importSemaphore(m_vkdB, *m_deviceB, *semaphoreB, m_semaphoreHandleType, nativeSemaphoreHandle, 0u);
1031 const vk::VkCommandBuffer commandBuffer = *commandBufferB;
1032 const vk::VkSemaphore semaphore = *semaphoreB;
1033 const vk::VkPipelineStageFlags dstStage = readSync.stageMask;
1034 const vk::VkSubmitInfo submitInfo =
1036 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1049 VK_CHECK(m_vkdB.queueSubmit(queueB, 1u, &submitInfo, DE_NULL));
1052 VK_CHECK(m_vkdA.queueWaitIdle(queueA));
1053 VK_CHECK(m_vkdB.queueWaitIdle(queueB));
1056 const Data expected = writeOp->getData();
1057 const Data actual = readOp->getData();
1059 DE_ASSERT(expected.size == actual.size);
1061 if (0 != deMemCmp(expected.data, actual.data, expected.size))
1063 const size_t maxBytesLogged = 256;
1064 std::ostringstream expectedData;
1065 std::ostringstream actualData;
1068 // Find first byte difference
1069 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1074 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1076 // Log 8 previous bytes before the first incorrect byte
1079 expectedData << "... ";
1080 actualData << "... ";
1087 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1089 expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1090 actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1093 if (expected.size > byteNdx)
1095 expectedData << "...";
1096 actualData << "...";
1099 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1100 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1102 m_resultCollector.fail("Memory contents don't match");
1106 catch (const tcu::NotSupportedError& error)
1108 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1110 catch (const tcu::TestError& error)
1112 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1115 // Move to next queue
1119 if (m_queueBNdx >= m_queueFamiliesB.size())
1123 if (m_queueANdx >= m_queueFamiliesA.size())
1125 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1131 return tcu::TestStatus::incomplete();
1135 return tcu::TestStatus::incomplete();
1141 void init (vk::SourceCollections& dst, TestConfig config) const
1143 const de::UniquePtr<OperationSupport> readOp (makeOperationSupport(config.readOp, config.resource));
1144 const de::UniquePtr<OperationSupport> writeOp (makeOperationSupport(config.writeOp, config.resource));
1146 readOp->initPrograms(dst);
1147 writeOp->initPrograms(dst);
1153 tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
1157 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryType;
1158 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreType;
1159 const char* nameSuffix;
1163 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1164 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1168 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1169 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR,
1173 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1174 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1178 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1179 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1183 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", ""));
1185 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
1187 const bool dedicated (dedicatedNdx == 1);
1188 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
1190 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
1191 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
1193 const OperationName writeOp = s_writeOps[writeOpNdx];
1194 const OperationName readOp = s_readOps[readOpNdx];
1195 const std::string opGroupName = getOperationName(writeOp) + "_" + getOperationName(readOp);
1198 de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1200 for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resources); ++resourceNdx)
1202 const ResourceDescription& resource = s_resources[resourceNdx];
1204 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1206 std::string name= getResourceName(resource) + cases[caseNdx].nameSuffix;
1208 if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1210 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryType, cases[caseNdx].semaphoreType, dedicated);
1212 opGroup->addChild(new InstanceFactory1<SharingTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, "", Progs(), config));
1219 dedicatedGroup->addChild(opGroup.release());
1222 group->addChild(dedicatedGroup.release());
1225 return group.release();
1228 } // synchronization