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 "vktSynchronizationOperationResources.hpp"
35 #include "vktExternalMemoryUtil.hpp"
37 #include "tcuResultCollector.hpp"
38 #include "tcuTestLog.hpp"
41 using namespace vkt::ExternalMemoryUtil;
45 namespace synchronization
52 TestConfig (const ResourceDescription& resource_,
53 OperationName writeOp_,
54 OperationName readOp_,
55 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType_,
56 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreHandleType_,
58 : resource (resource_)
61 , memoryHandleType (memoryHandleType_)
62 , semaphoreHandleType (semaphoreHandleType_)
63 , dedicated (dedicated_)
67 const ResourceDescription resource;
68 const OperationName writeOp;
69 const OperationName readOp;
70 const vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType;
71 const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreHandleType;
75 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
77 if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
78 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT;
80 return (availableFlags & neededFlags) != 0;
83 class SimpleAllocation : public vk::Allocation
86 SimpleAllocation (const vk::DeviceInterface& vkd,
88 const vk::VkDeviceMemory memory);
89 ~SimpleAllocation (void);
92 const vk::DeviceInterface& m_vkd;
93 const vk::VkDevice m_device;
96 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface& vkd,
98 const vk::VkDeviceMemory memory)
99 : Allocation (memory, 0, DE_NULL)
105 SimpleAllocation::~SimpleAllocation (void)
107 m_vkd.freeMemory(m_device, getMemory(), DE_NULL);
113 DeviceId (deUint32 vendorId,
114 deUint32 driverVersion,
115 const deUint8 driverUUID[VK_UUID_SIZE],
116 const deUint8 deviceUUID[VK_UUID_SIZE]);
118 bool operator== (const DeviceId& other) const;
119 bool operator|= (const DeviceId& other) const;
122 const deUint32 m_vendorId;
123 const deUint32 m_driverVersion;
124 deUint8 m_driverUUID[VK_UUID_SIZE];
125 deUint8 m_deviceUUID[VK_UUID_SIZE];
128 DeviceId::DeviceId (deUint32 vendorId,
129 deUint32 driverVersion,
130 const deUint8 driverUUID[VK_UUID_SIZE],
131 const deUint8 deviceUUID[VK_UUID_SIZE])
132 : m_vendorId (vendorId)
133 , m_driverVersion (driverVersion)
135 deMemcpy(m_driverUUID, driverUUID, sizeof(m_driverUUID));
136 deMemcpy(m_deviceUUID, deviceUUID, sizeof(m_deviceUUID));
139 bool DeviceId::operator== (const DeviceId& other) const
144 if (m_vendorId != other.m_vendorId)
147 if (m_driverVersion != other.m_driverVersion)
150 if (deMemCmp(m_driverUUID, other.m_driverUUID, sizeof(m_driverUUID)) != 0)
153 return deMemCmp(m_deviceUUID, other.m_deviceUUID, sizeof(m_deviceUUID)) == 0;
156 DeviceId getDeviceId (const vk::InstanceInterface& vki,
157 vk::VkPhysicalDevice physicalDevice)
159 vk::VkPhysicalDeviceIDPropertiesKHR propertiesId;
160 vk::VkPhysicalDeviceProperties2KHR properties;
162 deMemset(&properties, 0, sizeof(properties));
163 deMemset(&propertiesId, 0, sizeof(propertiesId));
165 propertiesId.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
167 properties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
168 properties.pNext = &propertiesId;
170 vki.getPhysicalDeviceProperties2KHR(physicalDevice, &properties);
172 return DeviceId(properties.properties.vendorID, properties.properties.driverVersion, propertiesId.driverUUID, propertiesId.deviceUUID);
175 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp)
179 std::vector<std::string> extensions;
181 extensions.push_back("VK_KHR_get_physical_device_properties2");
183 extensions.push_back("VK_KHR_external_semaphore_capabilities");
184 extensions.push_back("VK_KHR_external_memory_capabilities");
186 return vk::createDefaultInstance(vkp, std::vector<std::string>(), extensions);
188 catch (const vk::Error& error)
190 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
191 TCU_THROW(NotSupportedError, "Required external memory extensions not supported by the instance");
197 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki,
198 vk::VkInstance instance,
199 const tcu::CommandLine& cmdLine)
201 return vk::chooseDevice(vki, instance, cmdLine);
204 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki, vk::VkInstance instance, const DeviceId& deviceId)
206 const std::vector<vk::VkPhysicalDevice> devices (vk::enumeratePhysicalDevices(vki, instance));
208 for (size_t deviceNdx = 0; deviceNdx < devices.size(); deviceNdx++)
210 if (deviceId == getDeviceId(vki, devices[deviceNdx]))
211 return devices[deviceNdx];
214 TCU_FAIL("No matching device found");
216 return (vk::VkPhysicalDevice)0;
219 vk::Move<vk::VkDevice> createDevice (const vk::InstanceInterface& vki,
220 vk::VkPhysicalDevice physicalDevice,
221 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryHandleType,
222 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreHandleType,
224 bool khrMemReqSupported)
226 const float priority = 0.0f;
227 const std::vector<vk::VkQueueFamilyProperties> queueFamilyProperties = vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
228 std::vector<deUint32> queueFamilyIndices (queueFamilyProperties.size(), 0xFFFFFFFFu);
229 std::vector<const char*> extensions;
232 extensions.push_back("VK_KHR_dedicated_allocation");
234 if (khrMemReqSupported)
235 extensions.push_back("VK_KHR_get_memory_requirements2");
237 extensions.push_back("VK_KHR_external_semaphore");
238 extensions.push_back("VK_KHR_external_memory");
240 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
241 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR
242 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR)
244 extensions.push_back("VK_KHR_external_semaphore_fd");
245 extensions.push_back("VK_KHR_external_memory_fd");
248 if (memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
249 || memoryHandleType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR
250 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR
251 || semaphoreHandleType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR)
253 extensions.push_back("VK_KHR_external_semaphore_win32");
254 extensions.push_back("VK_KHR_external_memory_win32");
259 std::vector<vk::VkDeviceQueueCreateInfo> queues;
261 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++)
263 const vk::VkDeviceQueueCreateInfo createInfo =
265 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
274 queues.push_back(createInfo);
277 const vk::VkDeviceCreateInfo createInfo =
279 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
283 (deUint32)queues.size(),
289 (deUint32)extensions.size(),
290 extensions.empty() ? DE_NULL : &extensions[0],
294 return vk::createDevice(vki, physicalDevice, &createInfo);
296 catch (const vk::Error& error)
298 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
299 TCU_THROW(NotSupportedError, "Required extensions not supported");
305 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
306 const vk::VkDevice device,
307 deUint32 familyIndex)
311 vkd.getDeviceQueue(device, familyIndex, 0u, &queue);
316 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vkd,
318 deUint32 queueFamilyIndex)
320 const vk::VkCommandPoolCreateInfo createInfo =
322 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
329 return vk::createCommandPool(vkd, device, &createInfo);
332 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface& vkd,
334 vk::VkCommandPool commandPool)
336 const vk::VkCommandBufferLevel level = vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY;
337 const vk::VkCommandBufferAllocateInfo allocateInfo =
339 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
347 return vk::allocateCommandBuffer(vkd, device, &allocateInfo);
350 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface& vkd,
353 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
354 deUint32& exportedMemoryTypeIndex,
356 bool getMemReq2Supported)
358 vk::VkMemoryRequirements memoryRequirements = { 0u, 0u, 0u, };
360 if (getMemReq2Supported)
362 const vk::VkBufferMemoryRequirementsInfo2KHR requirementInfo =
364 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
368 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
370 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
375 vk::VkMemoryRequirements2KHR requirements =
377 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
378 &dedicatedRequirements,
381 vkd.getBufferMemoryRequirements2KHR(device, &requirementInfo, &requirements);
383 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
384 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation");
386 memoryRequirements = requirements.memoryRequirements;
390 vkd.getBufferMemoryRequirements(device, buffer, &memoryRequirements);
394 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, memoryRequirements, externalType, dedicated ? buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex);
395 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
397 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
400 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface& vkd,
403 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
404 deUint32& exportedMemoryTypeIndex,
406 bool getMemReq2Supported)
408 vk::VkMemoryRequirements memoryRequirements = { 0u, 0u, 0u, };
410 if (getMemReq2Supported)
412 const vk::VkImageMemoryRequirementsInfo2KHR requirementInfo =
414 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
418 vk::VkMemoryDedicatedRequirementsKHR dedicatedRequirements =
420 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
425 vk::VkMemoryRequirements2KHR requirements =
427 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
428 &dedicatedRequirements,
431 vkd.getImageMemoryRequirements2KHR(device, &requirementInfo, &requirements);
433 if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
434 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation");
436 memoryRequirements = requirements.memoryRequirements;
440 vkd.getImageMemoryRequirements(device, image, &memoryRequirements);
443 vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, memoryRequirements, externalType, dedicated ? image : (vk::VkImage)0, exportedMemoryTypeIndex);
444 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
446 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
449 de::MovePtr<Resource> createResource (const vk::DeviceInterface& vkd,
451 const ResourceDescription& resourceDesc,
452 const std::vector<deUint32>& queueFamilyIndices,
453 const OperationSupport& readOp,
454 const OperationSupport& writeOp,
455 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
456 deUint32& exportedMemoryTypeIndex,
458 bool getMemReq2Supported)
460 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
462 const vk::VkExtent3D extent =
464 (deUint32)resourceDesc.size.x(),
465 de::max(1u, (deUint32)resourceDesc.size.y()),
466 de::max(1u, (deUint32)resourceDesc.size.z())
468 const vk::VkImageSubresourceRange subresourceRange =
470 resourceDesc.imageAspect,
476 const vk::VkImageSubresourceLayers subresourceLayers =
478 resourceDesc.imageAspect,
483 const vk::VkExternalMemoryImageCreateInfoKHR externalInfo =
485 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
487 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
489 const vk::VkImageCreateInfo createInfo =
491 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
495 resourceDesc.imageType,
496 resourceDesc.imageFormat,
500 vk::VK_SAMPLE_COUNT_1_BIT,
501 vk::VK_IMAGE_TILING_OPTIMAL,
502 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
503 vk::VK_SHARING_MODE_EXCLUSIVE,
505 (deUint32)queueFamilyIndices.size(),
506 &queueFamilyIndices[0],
507 vk::VK_IMAGE_LAYOUT_UNDEFINED
510 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
511 de::MovePtr<vk::Allocation> allocation = allocateAndBindMemory(vkd, device, *image, externalType, exportedMemoryTypeIndex, dedicated, getMemReq2Supported);
513 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
517 const vk::VkDeviceSize offset = 0u;
518 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
519 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
520 const vk:: VkExternalMemoryBufferCreateInfoKHR externalInfo =
522 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
524 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
526 const vk::VkBufferCreateInfo createInfo =
528 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
534 vk::VK_SHARING_MODE_EXCLUSIVE,
535 (deUint32)queueFamilyIndices.size(),
536 &queueFamilyIndices[0]
538 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
539 de::MovePtr<vk::Allocation> allocation = allocateAndBindMemory(vkd, device, *buffer, externalType, exportedMemoryTypeIndex, dedicated, getMemReq2Supported);
541 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
545 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
548 NativeHandle& nativeHandle,
549 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
550 deUint32 exportedMemoryTypeIndex,
553 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vkd, device, buffer);
554 vk::Move<vk::VkDeviceMemory> memory = dedicated
555 ? importDedicatedMemory(vkd, device, buffer, requirements, externalType, exportedMemoryTypeIndex, nativeHandle)
556 : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle);
558 VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
560 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
563 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface& vkd,
566 NativeHandle& nativeHandle,
567 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
568 deUint32 exportedMemoryTypeIndex,
571 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vkd, device, image);
572 vk::Move<vk::VkDeviceMemory> memory = dedicated
573 ? importDedicatedMemory(vkd, device, image, requirements, externalType, exportedMemoryTypeIndex, nativeHandle)
574 : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle);
575 VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
577 return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
580 de::MovePtr<Resource> importResource (const vk::DeviceInterface& vkd,
582 const ResourceDescription& resourceDesc,
583 const std::vector<deUint32>& queueFamilyIndices,
584 const OperationSupport& readOp,
585 const OperationSupport& writeOp,
586 NativeHandle& nativeHandle,
587 vk::VkExternalMemoryHandleTypeFlagBitsKHR externalType,
588 deUint32 exportedMemoryTypeIndex,
591 if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
593 const vk::VkExtent3D extent =
595 (deUint32)resourceDesc.size.x(),
596 de::max(1u, (deUint32)resourceDesc.size.y()),
597 de::max(1u, (deUint32)resourceDesc.size.z())
599 const vk::VkImageSubresourceRange subresourceRange =
601 resourceDesc.imageAspect,
607 const vk::VkImageSubresourceLayers subresourceLayers =
609 resourceDesc.imageAspect,
614 const vk:: VkExternalMemoryImageCreateInfoKHR externalInfo =
616 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
618 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
620 const vk::VkImageCreateInfo createInfo =
622 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
626 resourceDesc.imageType,
627 resourceDesc.imageFormat,
631 vk::VK_SAMPLE_COUNT_1_BIT,
632 vk::VK_IMAGE_TILING_OPTIMAL,
633 readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
634 vk::VK_SHARING_MODE_EXCLUSIVE,
636 (deUint32)queueFamilyIndices.size(),
637 &queueFamilyIndices[0],
638 vk::VK_IMAGE_LAYOUT_UNDEFINED
641 vk::Move<vk::VkImage> image = vk::createImage(vkd, device, &createInfo);
642 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *image, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
644 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
648 const vk::VkDeviceSize offset = 0u;
649 const vk::VkDeviceSize size = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
650 const vk::VkBufferUsageFlags usage = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
651 const vk:: VkExternalMemoryBufferCreateInfoKHR externalInfo =
653 vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
655 (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
657 const vk::VkBufferCreateInfo createInfo =
659 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
665 vk::VK_SHARING_MODE_EXCLUSIVE,
666 (deUint32)queueFamilyIndices.size(),
667 &queueFamilyIndices[0]
669 vk::Move<vk::VkBuffer> buffer = vk::createBuffer(vkd, device, &createInfo);
670 de::MovePtr<vk::Allocation> allocation = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
672 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
676 void recordWriteBarrier (const vk::DeviceInterface& vkd,
677 vk::VkCommandBuffer commandBuffer,
678 const Resource& resource,
679 const SyncInfo& writeSync,
680 deUint32 writeQueueFamilyIndex,
681 const SyncInfo& readSync)
683 const vk::VkPipelineStageFlags srcStageMask = writeSync.stageMask;
684 const vk::VkAccessFlags srcAccessMask = writeSync.accessMask;
686 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
687 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
689 const vk::VkDependencyFlags dependencyFlags = 0;
691 if (resource.getType() == RESOURCE_TYPE_IMAGE)
693 const vk::VkImageMemoryBarrier barrier =
695 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
701 writeSync.imageLayout,
702 readSync.imageLayout,
704 writeQueueFamilyIndex,
705 VK_QUEUE_FAMILY_EXTERNAL_KHR,
707 resource.getImage().handle,
708 resource.getImage().subresourceRange
711 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
715 const vk::VkBufferMemoryBarrier barrier =
717 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
723 writeQueueFamilyIndex,
724 VK_QUEUE_FAMILY_EXTERNAL_KHR,
726 resource.getBuffer().handle,
731 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
735 void recordReadBarrier (const vk::DeviceInterface& vkd,
736 vk::VkCommandBuffer commandBuffer,
737 const Resource& resource,
738 const SyncInfo& writeSync,
739 const SyncInfo& readSync,
740 deUint32 readQueueFamilyIndex)
742 const vk::VkPipelineStageFlags srcStageMask = readSync.stageMask;
743 const vk::VkAccessFlags srcAccessMask = readSync.accessMask;
745 const vk::VkPipelineStageFlags dstStageMask = readSync.stageMask;
746 const vk::VkAccessFlags dstAccessMask = readSync.accessMask;
748 const vk::VkDependencyFlags dependencyFlags = 0;
750 if (resource.getType() == RESOURCE_TYPE_IMAGE)
752 const vk::VkImageMemoryBarrier barrier =
754 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
760 writeSync.imageLayout,
761 readSync.imageLayout,
763 VK_QUEUE_FAMILY_EXTERNAL_KHR,
764 readQueueFamilyIndex,
766 resource.getImage().handle,
767 resource.getImage().subresourceRange
770 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
774 const vk::VkBufferMemoryBarrier barrier =
776 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
782 VK_QUEUE_FAMILY_EXTERNAL_KHR,
783 readQueueFamilyIndex,
785 resource.getBuffer().handle,
790 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
794 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
796 std::vector<deUint32> indices (properties.size(), 0);
798 for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
804 class SharingTestInstance : public TestInstance
807 SharingTestInstance (Context& context,
810 virtual tcu::TestStatus iterate (void);
813 const TestConfig m_config;
814 const de::UniquePtr<OperationSupport> m_supportWriteOp;
815 const de::UniquePtr<OperationSupport> m_supportReadOp;
817 const vk::Unique<vk::VkInstance> m_instanceA;
819 const vk::InstanceDriver m_vkiA;
820 const vk::VkPhysicalDevice m_physicalDeviceA;
821 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesA;
822 const std::vector<deUint32> m_queueFamilyIndicesA;
824 const bool m_getMemReq2Supported;
826 const vk::Unique<vk::VkDevice> m_deviceA;
827 const vk::DeviceDriver m_vkdA;
829 const vk::Unique<vk::VkInstance> m_instanceB;
830 const vk::InstanceDriver m_vkiB;
831 const vk::VkPhysicalDevice m_physicalDeviceB;
832 const std::vector<vk::VkQueueFamilyProperties> m_queueFamiliesB;
833 const std::vector<deUint32> m_queueFamilyIndicesB;
834 const vk::Unique<vk::VkDevice> m_deviceB;
835 const vk::DeviceDriver m_vkdB;
837 const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR m_semaphoreHandleType;
838 const vk::VkExternalMemoryHandleTypeFlagBitsKHR m_memoryHandleType;
840 // \todo Should this be moved to the group same way as in the other tests?
841 PipelineCacheData m_pipelineCacheData;
842 tcu::ResultCollector m_resultCollector;
847 SharingTestInstance::SharingTestInstance (Context& context,
849 : TestInstance (context)
851 , m_supportWriteOp (makeOperationSupport(config.writeOp, config.resource))
852 , m_supportReadOp (makeOperationSupport(config.readOp, config.resource))
854 , m_instanceA (createInstance(context.getPlatformInterface()))
856 , m_vkiA (context.getPlatformInterface(), *m_instanceA)
857 , m_physicalDeviceA (getPhysicalDevice(m_vkiA, *m_instanceA, context.getTestContext().getCommandLine()))
858 , m_queueFamiliesA (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiA, m_physicalDeviceA))
859 , m_queueFamilyIndicesA (getFamilyIndices(m_queueFamiliesA))
860 , m_getMemReq2Supported (de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_get_memory_requirements2"))
861 , m_deviceA (createDevice(m_vkiA, m_physicalDeviceA, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported))
862 , m_vkdA (m_vkiA, *m_deviceA)
864 , m_instanceB (createInstance(context.getPlatformInterface()))
866 , m_vkiB (context.getPlatformInterface(), *m_instanceB)
867 , m_physicalDeviceB (getPhysicalDevice(m_vkiB, *m_instanceB, getDeviceId(m_vkiA, m_physicalDeviceA)))
868 , m_queueFamiliesB (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiB, m_physicalDeviceB))
869 , m_queueFamilyIndicesB (getFamilyIndices(m_queueFamiliesB))
870 , m_deviceB (createDevice(m_vkiB, m_physicalDeviceB, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported))
871 , m_vkdB (m_vkiB, *m_deviceB)
873 , m_semaphoreHandleType (m_config.semaphoreHandleType)
874 , m_memoryHandleType (m_config.memoryHandleType)
876 , m_resultCollector (context.getTestContext().getLog())
880 TestLog& log = m_context.getTestContext().getLog();
882 // Check resource support
883 if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
885 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR externalInfo =
887 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
891 const vk::VkPhysicalDeviceImageFormatInfo2KHR imageFormatInfo =
893 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
895 m_config.resource.imageFormat,
896 m_config.resource.imageType,
897 vk::VK_IMAGE_TILING_OPTIMAL,
898 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
901 vk::VkExternalImageFormatPropertiesKHR externalProperties =
903 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
907 vk::VkImageFormatProperties2KHR formatProperties =
909 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
921 const vk::VkResult res = m_vkiA.getPhysicalDeviceImageFormatProperties2KHR(m_physicalDeviceA, &imageFormatInfo, &formatProperties);
923 if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
924 TCU_THROW(NotSupportedError, "Image format not supported");
926 VK_CHECK(res); // Check other errors
929 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
931 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
932 TCU_THROW(NotSupportedError, "Exporting image resource not supported");
934 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
935 TCU_THROW(NotSupportedError, "Importing image resource not supported");
937 if (!m_config.dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
939 TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
944 const vk::VkPhysicalDeviceExternalBufferInfoKHR info =
946 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
950 m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
953 vk::VkExternalBufferPropertiesKHR properties =
955 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
959 m_vkiA.getPhysicalDeviceExternalBufferPropertiesKHR(m_physicalDeviceA, &info, &properties);
961 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
963 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0
964 || (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
965 TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported");
967 if (!m_config.dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
969 TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
973 // Check semaphore support
975 const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR info =
977 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
979 m_semaphoreHandleType
981 vk::VkExternalSemaphorePropertiesKHR properties;
983 m_vkiA.getPhysicalDeviceExternalSemaphorePropertiesKHR(m_physicalDeviceA, &info, &properties);
985 log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
987 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0
988 || (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
989 TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported");
993 tcu::TestStatus SharingTestInstance::iterate (void)
995 TestLog& log (m_context.getTestContext().getLog());
997 const deUint32 queueFamilyA = (deUint32)m_queueANdx;
998 const deUint32 queueFamilyB = (deUint32)m_queueBNdx;
1000 const tcu::ScopedLogSection queuePairSection (log,
1001 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB),
1002 "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB));
1004 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(m_vkdA, *m_deviceA, m_semaphoreHandleType));
1005 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(m_vkdB, *m_deviceB));
1007 deUint32 exportedMemoryTypeIndex = ~0U;
1008 const de::UniquePtr<Resource> resourceA (createResource(m_vkdA, *m_deviceA, m_config.resource, m_queueFamilyIndicesA, *m_supportReadOp, *m_supportWriteOp, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated, m_getMemReq2Supported));
1010 NativeHandle nativeMemoryHandle;
1011 getMemoryNative(m_vkdA, *m_deviceA, resourceA->getMemory(), m_memoryHandleType, nativeMemoryHandle);
1013 const de::UniquePtr<Resource> resourceB (importResource(m_vkdB, *m_deviceB, m_config.resource, m_queueFamilyIndicesB, *m_supportReadOp, *m_supportWriteOp, nativeMemoryHandle, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated));
1017 const vk::VkQueue queueA (getQueue(m_vkdA, *m_deviceA, queueFamilyA));
1018 const vk::Unique<vk::VkCommandPool> commandPoolA (createCommandPool(m_vkdA, *m_deviceA, queueFamilyA));
1019 const vk::Unique<vk::VkCommandBuffer> commandBufferA (createCommandBuffer(m_vkdA, *m_deviceA, *commandPoolA));
1020 vk::SimpleAllocator allocatorA (m_vkdA, *m_deviceA, vk::getPhysicalDeviceMemoryProperties(m_vkiA, m_physicalDeviceA));
1021 const std::vector<std::string> deviceExtensionsA;
1022 OperationContext operationContextA (m_vkiA, m_vkdA, m_physicalDeviceA, *m_deviceA, allocatorA, deviceExtensionsA, m_context.getBinaryCollection(), m_pipelineCacheData);
1024 if (!checkQueueFlags(m_queueFamiliesA[m_queueANdx].queueFlags , m_supportWriteOp->getQueueFlags(operationContextA)))
1025 TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
1027 const vk::VkQueue queueB (getQueue(m_vkdB, *m_deviceB, queueFamilyB));
1028 const vk::Unique<vk::VkCommandPool> commandPoolB (createCommandPool(m_vkdB, *m_deviceB, queueFamilyB));
1029 const vk::Unique<vk::VkCommandBuffer> commandBufferB (createCommandBuffer(m_vkdB, *m_deviceB, *commandPoolB));
1030 vk::SimpleAllocator allocatorB (m_vkdB, *m_deviceB, vk::getPhysicalDeviceMemoryProperties(m_vkiB, m_physicalDeviceB));
1031 const std::vector<std::string> deviceExtensionsB;
1032 OperationContext operationContextB (m_vkiB, m_vkdB, m_physicalDeviceB, *m_deviceB, allocatorB, deviceExtensionsB, m_context.getBinaryCollection(), m_pipelineCacheData);
1034 if (!checkQueueFlags(m_queueFamiliesB[m_queueBNdx].queueFlags , m_supportReadOp->getQueueFlags(operationContextB)))
1035 TCU_THROW(NotSupportedError, "Operation not supported by the destination queue");
1037 const de::UniquePtr<Operation> writeOp (m_supportWriteOp->build(operationContextA, *resourceA));
1038 const de::UniquePtr<Operation> readOp (m_supportReadOp->build(operationContextB, *resourceB));
1040 const SyncInfo writeSync = writeOp->getSyncInfo();
1041 const SyncInfo readSync = readOp->getSyncInfo();
1043 beginCommandBuffer(m_vkdA, *commandBufferA);
1044 writeOp->recordCommands(*commandBufferA);
1045 recordWriteBarrier(m_vkdA, *commandBufferA, *resourceA, writeSync, queueFamilyA, readSync);
1046 endCommandBuffer(m_vkdA, *commandBufferA);
1048 beginCommandBuffer(m_vkdB, *commandBufferB);
1049 recordReadBarrier(m_vkdB, *commandBufferB, *resourceB, writeSync, readSync, queueFamilyB);
1050 readOp->recordCommands(*commandBufferB);
1051 endCommandBuffer(m_vkdB, *commandBufferB);
1054 const vk::VkCommandBuffer commandBuffer = *commandBufferA;
1055 const vk::VkSemaphore semaphore = *semaphoreA;
1056 const vk::VkSubmitInfo submitInfo =
1058 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1071 VK_CHECK(m_vkdA.queueSubmit(queueA, 1u, &submitInfo, DE_NULL));
1074 NativeHandle nativeSemaphoreHandle;
1076 getSemaphoreNative(m_vkdA, *m_deviceA, *semaphoreA, m_semaphoreHandleType, nativeSemaphoreHandle);
1077 importSemaphore(m_vkdB, *m_deviceB, *semaphoreB, m_semaphoreHandleType, nativeSemaphoreHandle, 0u);
1081 const vk::VkCommandBuffer commandBuffer = *commandBufferB;
1082 const vk::VkSemaphore semaphore = *semaphoreB;
1083 const vk::VkPipelineStageFlags dstStage = readSync.stageMask;
1084 const vk::VkSubmitInfo submitInfo =
1086 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1099 VK_CHECK(m_vkdB.queueSubmit(queueB, 1u, &submitInfo, DE_NULL));
1102 VK_CHECK(m_vkdA.queueWaitIdle(queueA));
1103 VK_CHECK(m_vkdB.queueWaitIdle(queueB));
1106 const Data expected = writeOp->getData();
1107 const Data actual = readOp->getData();
1109 DE_ASSERT(expected.size == actual.size);
1111 if (0 != deMemCmp(expected.data, actual.data, expected.size))
1113 const size_t maxBytesLogged = 256;
1114 std::ostringstream expectedData;
1115 std::ostringstream actualData;
1118 // Find first byte difference
1119 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1124 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1126 // Log 8 previous bytes before the first incorrect byte
1129 expectedData << "... ";
1130 actualData << "... ";
1137 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1139 expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1140 actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1143 if (expected.size > byteNdx)
1145 expectedData << "...";
1146 actualData << "...";
1149 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1150 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1152 m_resultCollector.fail("Memory contents don't match");
1156 catch (const tcu::NotSupportedError& error)
1158 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1160 catch (const tcu::TestError& error)
1162 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1165 // Move to next queue
1169 if (m_queueBNdx >= m_queueFamiliesB.size())
1173 if (m_queueANdx >= m_queueFamiliesA.size())
1175 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1181 return tcu::TestStatus::incomplete();
1185 return tcu::TestStatus::incomplete();
1191 void init (vk::SourceCollections& dst, TestConfig config) const
1193 const de::UniquePtr<OperationSupport> readOp (makeOperationSupport(config.readOp, config.resource));
1194 const de::UniquePtr<OperationSupport> writeOp (makeOperationSupport(config.writeOp, config.resource));
1196 readOp->initPrograms(dst);
1197 writeOp->initPrograms(dst);
1203 tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
1207 vk::VkExternalMemoryHandleTypeFlagBitsKHR memoryType;
1208 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR semaphoreType;
1209 const char* nameSuffix;
1213 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1214 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1218 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1219 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR,
1223 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1224 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1228 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1229 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1233 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", ""));
1235 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
1237 const bool dedicated (dedicatedNdx == 1);
1238 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
1240 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
1241 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
1243 const OperationName writeOp = s_writeOps[writeOpNdx];
1244 const OperationName readOp = s_readOps[readOpNdx];
1245 const std::string opGroupName = getOperationName(writeOp) + "_" + getOperationName(readOp);
1248 de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1250 for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resources); ++resourceNdx)
1252 const ResourceDescription& resource = s_resources[resourceNdx];
1254 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1256 std::string name= getResourceName(resource) + cases[caseNdx].nameSuffix;
1258 if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1260 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryType, cases[caseNdx].semaphoreType, dedicated);
1262 opGroup->addChild(new InstanceFactory1<SharingTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, "", Progs(), config));
1269 dedicatedGroup->addChild(opGroup.release());
1272 group->addChild(dedicatedGroup.release());
1275 return group.release();
1278 } // synchronization