cross_instance sync tests: add support for non-KMT Win32 handles
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / synchronization / vktSynchronizationCrossInstanceSharingTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Synchronization tests for resources shared between instances.
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationCrossInstanceSharingTests.hpp"
25
26 #include "vkDeviceUtil.hpp"
27 #include "vkPlatform.hpp"
28
29 #include "vktTestCaseUtil.hpp"
30
31 #include "vktSynchronizationUtil.hpp"
32 #include "vktSynchronizationOperation.hpp"
33 #include "vktSynchronizationOperationTestData.hpp"
34 #include "vktExternalMemoryUtil.hpp"
35
36 #include "tcuResultCollector.hpp"
37 #include "tcuTestLog.hpp"
38
39 using tcu::TestLog;
40 using namespace vkt::ExternalMemoryUtil;
41
42 namespace vkt
43 {
44 namespace synchronization
45 {
46 namespace
47 {
48
49 struct TestConfig
50 {
51                                                                 TestConfig              (const ResourceDescription&                                             resource_,
52                                                                                                  OperationName                                                                  writeOp_,
53                                                                                                  OperationName                                                                  readOp_,
54                                                                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR              memoryHandleType_,
55                                                                                                  vk::VkExternalSemaphoreHandleTypeFlagBitsKHR   semaphoreHandleType_,
56                                                                                                  bool                                                                                   dedicated_)
57                 : resource                              (resource_)
58                 , writeOp                               (writeOp_)
59                 , readOp                                (readOp_)
60                 , memoryHandleType              (memoryHandleType_)
61                 , semaphoreHandleType   (semaphoreHandleType_)
62                 , dedicated                             (dedicated_)
63         {
64         }
65
66         const ResourceDescription                                                       resource;
67         const OperationName                                                                     writeOp;
68         const OperationName                                                                     readOp;
69         const vk::VkExternalMemoryHandleTypeFlagBitsKHR         memoryHandleType;
70         const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR      semaphoreHandleType;
71         const bool                                                                                      dedicated;
72 };
73
74 bool checkQueueFlags (vk::VkQueueFlags availableFlags, const vk::VkQueueFlags neededFlags)
75 {
76         if ((availableFlags & (vk::VK_QUEUE_GRAPHICS_BIT | vk::VK_QUEUE_COMPUTE_BIT)) != 0)
77                 availableFlags |= vk::VK_QUEUE_TRANSFER_BIT;
78
79         return (availableFlags & neededFlags) != 0;
80 }
81
82 class SimpleAllocation : public vk::Allocation
83 {
84 public:
85                                                                 SimpleAllocation        (const vk::DeviceInterface&     vkd,
86                                                                                                          vk::VkDevice                           device,
87                                                                                                          const vk::VkDeviceMemory       memory);
88                                                                 ~SimpleAllocation       (void);
89
90 private:
91         const vk::DeviceInterface&      m_vkd;
92         const vk::VkDevice                      m_device;
93 };
94
95 SimpleAllocation::SimpleAllocation (const vk::DeviceInterface&  vkd,
96                                                                         vk::VkDevice                            device,
97                                                                         const vk::VkDeviceMemory        memory)
98         : Allocation    (memory, 0, DE_NULL)
99         , m_vkd                 (vkd)
100         , m_device              (device)
101 {
102 }
103
104 SimpleAllocation::~SimpleAllocation (void)
105 {
106         m_vkd.freeMemory(m_device, getMemory(), DE_NULL);
107 }
108
109 class DeviceId
110 {
111 public:
112                                         DeviceId                (deUint32               vendorId,
113                                                                          deUint32               driverVersion,
114                                                                          const deUint8  driverUUID[VK_UUID_SIZE],
115                                                                          const deUint8  deviceUUID[VK_UUID_SIZE]);
116
117         bool                    operator==              (const DeviceId& other) const;
118         bool                    operator|=              (const DeviceId& other) const;
119
120 private:
121         const deUint32  m_vendorId;
122         const deUint32  m_driverVersion;
123         deUint8                 m_driverUUID[VK_UUID_SIZE];
124         deUint8                 m_deviceUUID[VK_UUID_SIZE];
125 };
126
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)
133 {
134         deMemcpy(m_driverUUID, driverUUID, sizeof(m_driverUUID));
135         deMemcpy(m_deviceUUID, deviceUUID, sizeof(m_deviceUUID));
136 }
137
138 bool DeviceId::operator== (const DeviceId& other) const
139 {
140         if (this == &other)
141                 return true;
142
143         if (m_vendorId != other.m_vendorId)
144                 return false;
145
146         if (m_driverVersion != other.m_driverVersion)
147                 return false;
148
149         if (deMemCmp(m_driverUUID, other.m_driverUUID, sizeof(m_driverUUID)) != 0)
150                 return false;
151
152         return deMemCmp(m_deviceUUID, other.m_deviceUUID, sizeof(m_deviceUUID)) == 0;
153 }
154
155 DeviceId getDeviceId (const vk::InstanceInterface&      vki,
156                                           vk::VkPhysicalDevice                  physicalDevice)
157 {
158         vk::VkPhysicalDeviceIDPropertiesKHR                     propertiesId;
159         vk::VkPhysicalDeviceProperties2KHR                      properties;
160
161         deMemset(&properties, 0, sizeof(properties));
162         deMemset(&propertiesId, 0, sizeof(propertiesId));
163
164         propertiesId.sType      = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
165
166         properties.sType        = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
167         properties.pNext        = &propertiesId;
168
169         vki.getPhysicalDeviceProperties2KHR(physicalDevice, &properties);
170
171         return DeviceId(properties.properties.vendorID, properties.properties.driverVersion, propertiesId.driverUUID, propertiesId.deviceUUID);
172 }
173
174 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface& vkp)
175 {
176         try
177         {
178                 std::vector<std::string> extensions;
179
180                 extensions.push_back("VK_KHR_get_physical_device_properties2");
181
182                 extensions.push_back("VK_KHR_external_semaphore_capabilities");
183                 extensions.push_back("VK_KHR_external_memory_capabilities");
184
185                 return vk::createDefaultInstance(vkp, std::vector<std::string>(), extensions);
186         }
187         catch (const vk::Error& error)
188         {
189                 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
190                         TCU_THROW(NotSupportedError, "Required external memory extensions not supported by the instance");
191                 else
192                         throw;
193         }
194 }
195
196 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface&    vki,
197                                                                                 vk::VkInstance                                  instance,
198                                                                                 const tcu::CommandLine&                 cmdLine)
199 {
200         return vk::chooseDevice(vki, instance, cmdLine);
201 }
202
203 vk::VkPhysicalDevice getPhysicalDevice (const vk::InstanceInterface& vki, vk::VkInstance instance, const DeviceId& deviceId)
204 {
205         const std::vector<vk::VkPhysicalDevice> devices (vk::enumeratePhysicalDevices(vki, instance));
206
207         for (size_t deviceNdx = 0; deviceNdx < devices.size(); deviceNdx++)
208         {
209                 if (deviceId == getDeviceId(vki, devices[deviceNdx]))
210                         return devices[deviceNdx];
211         }
212
213         TCU_FAIL("No matching device found");
214
215         return (vk::VkPhysicalDevice)0;
216 }
217
218 vk::Move<vk::VkDevice> createDevice (const vk::InstanceInterface&                                       vki,
219                                                                          vk::VkPhysicalDevice                                                   physicalDevice,
220                                                                          vk::VkExternalMemoryHandleTypeFlagBitsKHR              memoryHandleType,
221                                                                          vk::VkExternalSemaphoreHandleTypeFlagBitsKHR   semaphoreHandleType,
222                                                                          bool                                                                                   dedicated)
223 {
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;
228
229         if (dedicated)
230                 extensions.push_back("VK_KHR_dedicated_allocation");
231
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");
235
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)
239         {
240                 extensions.push_back("VK_KHR_external_semaphore_fd");
241                 extensions.push_back("VK_KHR_external_memory_fd");
242         }
243
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)
248         {
249                 extensions.push_back("VK_KHR_external_semaphore_win32");
250                 extensions.push_back("VK_KHR_external_memory_win32");
251         }
252
253         try
254         {
255                 std::vector<vk::VkDeviceQueueCreateInfo>        queues;
256
257                 for (size_t ndx = 0; ndx < queueFamilyProperties.size(); ndx++)
258                 {
259                         const vk::VkDeviceQueueCreateInfo       createInfo      =
260                         {
261                                 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
262                                 DE_NULL,
263                                 0u,
264
265                                 (deUint32)ndx,
266                                 1u,
267                                 &priority
268                         };
269
270                         queues.push_back(createInfo);
271                 }
272
273                 const vk::VkDeviceCreateInfo            createInfo                      =
274                 {
275                         vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
276                         DE_NULL,
277                         0u,
278
279                         (deUint32)queues.size(),
280                         &queues[0],
281
282                         0u,
283                         DE_NULL,
284
285                         (deUint32)extensions.size(),
286                         extensions.empty() ? DE_NULL : &extensions[0],
287                         0u
288                 };
289
290                 return vk::createDevice(vki, physicalDevice, &createInfo);
291         }
292         catch (const vk::Error& error)
293         {
294                 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
295                         TCU_THROW(NotSupportedError, "Required extensions not supported");
296                 else
297                         throw;
298         }
299 }
300
301 vk::VkQueue getQueue (const vk::DeviceInterface&        vkd,
302                                           const vk::VkDevice                    device,
303                                           deUint32                                              familyIndex)
304 {
305         vk::VkQueue queue;
306
307         vkd.getDeviceQueue(device, familyIndex, 0u, &queue);
308
309         return queue;
310 }
311
312 vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface&       vkd,
313                                                                                            vk::VkDevice                                 device,
314                                                                                            deUint32                                             queueFamilyIndex)
315 {
316         const vk::VkCommandPoolCreateInfo       createInfo                      =
317         {
318                 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
319                 DE_NULL,
320
321                 0u,
322                 queueFamilyIndex
323         };
324
325         return vk::createCommandPool(vkd, device, &createInfo);
326 }
327
328 vk::Move<vk::VkCommandBuffer> createCommandBuffer (const vk::DeviceInterface&   vkd,
329                                                                                                    vk::VkDevice                                 device,
330                                                                                                    vk::VkCommandPool                    commandPool)
331 {
332         const vk::VkCommandBufferLevel                  level                   = vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY;
333         const vk::VkCommandBufferAllocateInfo   allocateInfo    =
334         {
335                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
336                 DE_NULL,
337
338                 commandPool,
339                 level,
340                 1u
341         };
342
343         return vk::allocateCommandBuffer(vkd, device, &allocateInfo);
344 }
345
346 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface&                                   vkd,
347                                                                                                    vk::VkDevice                                                                 device,
348                                                                                                    vk::VkBuffer                                                                 buffer,
349                                                                                                    vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
350                                                                                                    bool                                                                                 dedicated)
351 {
352         const vk::VkBufferMemoryRequirementsInfo2KHR    requirementInfo =
353         {
354                 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR,
355                 DE_NULL,
356                 buffer
357         };
358         vk::VkMemoryDedicatedRequirementsKHR                    dedicatedRequirements =
359         {
360                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
361                 DE_NULL,
362                 VK_FALSE,
363                 VK_FALSE
364         };
365         vk::VkMemoryRequirements2KHR                                    requirements    =
366         {
367                 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
368                 &dedicatedRequirements,
369                 { 0u, 0u, 0u, }
370         };
371         vkd.getBufferMemoryRequirements2KHR(device, &requirementInfo, &requirements);
372
373         if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
374                 TCU_THROW(NotSupportedError, "Memory requires dedicated allocation");
375
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));
378
379         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
380 }
381
382 de::MovePtr<vk::Allocation> allocateAndBindMemory (const vk::DeviceInterface&                                   vkd,
383                                                                                                    vk::VkDevice                                                                 device,
384                                                                                                    vk::VkImage                                                                  image,
385                                                                                                    vk::VkExternalMemoryHandleTypeFlagBitsKHR    externalType,
386                                                                                                    bool                                                                                 dedicated)
387 {
388         const vk::VkImageMemoryRequirementsInfo2KHR     requirementInfo =
389         {
390                 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR,
391                 DE_NULL,
392                 image
393         };
394         vk::VkMemoryDedicatedRequirementsKHR                    dedicatedRequirements =
395         {
396                 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR,
397                 DE_NULL,
398                 VK_FALSE,
399                 VK_FALSE
400         };
401         vk::VkMemoryRequirements2KHR                                    requirements    =
402         {
403                 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR,
404                 &dedicatedRequirements,
405                 { 0u, 0u, 0u, }
406         };
407         vkd.getImageMemoryRequirements2KHR(device, &requirementInfo, &requirements);
408
409         if (!dedicated && dedicatedRequirements.requiresDedicatedAllocation)
410                 TCU_THROW(NotSupportedError, "Memomry requires dedicated allocation");
411
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));
414
415         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
416 }
417
418 de::MovePtr<Resource> createResource (const vk::DeviceInterface&                                vkd,
419                                                                           vk::VkDevice                                                          device,
420                                                                           const ResourceDescription&                            resourceDesc,
421                                                                           const std::vector<deUint32>&                          queueFamilyIndices,
422                                                                           const OperationSupport&                                       readOp,
423                                                                           const OperationSupport&                                       writeOp,
424                                                                           vk::VkExternalMemoryHandleTypeFlagBitsKHR     externalType,
425                                                                           bool                                                                          dedicated)
426 {
427         if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
428         {
429                 const vk::VkExtent3D                            extent                                  =
430                 {
431                         (deUint32)resourceDesc.size.x(),
432                         de::max(1u, (deUint32)resourceDesc.size.y()),
433                         de::max(1u, (deUint32)resourceDesc.size.z())
434                 };
435                 const vk::VkImageSubresourceRange       subresourceRange                =
436                 {
437                         resourceDesc.imageAspect,
438                         0u,
439                         1u,
440                         0u,
441                         1u
442                 };
443                 const vk::VkImageSubresourceLayers      subresourceLayers               =
444                 {
445                         resourceDesc.imageAspect,
446                         0u,
447                         0u,
448                         1u
449                 };
450                 const vk::VkExternalMemoryImageCreateInfoKHR externalInfo =
451                 {
452                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
453                         DE_NULL,
454                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
455                 };
456                 const vk::VkImageCreateInfo                     createInfo                              =
457                 {
458                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
459                         &externalInfo,
460                         0u,
461
462                         resourceDesc.imageType,
463                         resourceDesc.imageFormat,
464                         extent,
465                         1u,
466                         1u,
467                         vk::VK_SAMPLE_COUNT_1_BIT,
468                         vk::VK_IMAGE_TILING_OPTIMAL,
469                         readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
470                         vk::VK_SHARING_MODE_EXCLUSIVE,
471
472                         (deUint32)queueFamilyIndices.size(),
473                         &queueFamilyIndices[0],
474                         vk::VK_IMAGE_LAYOUT_UNDEFINED
475                 };
476
477                 vk::Move<vk::VkImage>                   image           = vk::createImage(vkd, device, &createInfo);
478                 de::MovePtr<vk::Allocation>             allocation      = allocateAndBindMemory(vkd, device, *image, externalType, dedicated);
479
480                 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
481         }
482         else
483         {
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    =
488                 {
489                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
490                         DE_NULL,
491                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
492                 };
493                 const vk::VkBufferCreateInfo                                    createInfo              =
494                 {
495                         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
496                         &externalInfo,
497                         0u,
498
499                         size,
500                         usage,
501                         vk::VK_SHARING_MODE_EXCLUSIVE,
502                         (deUint32)queueFamilyIndices.size(),
503                         &queueFamilyIndices[0]
504                 };
505                 vk::Move<vk::VkBuffer>          buffer          = vk::createBuffer(vkd, device, &createInfo);
506                 de::MovePtr<vk::Allocation>     allocation      = allocateAndBindMemory(vkd, device, *buffer, externalType, dedicated);
507
508                 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
509         }
510 }
511
512 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface&                                     vkd,
513                                                                                                  vk::VkDevice                                                           device,
514                                                                                                  vk::VkBuffer                                                           buffer,
515                                                                                                  NativeHandle&                                                          nativeHandle,
516                                                                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
517                                                                                                  bool                                                                           dedicated)
518 {
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);
523
524         VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
525
526         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
527 }
528
529 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface&                                     vkd,
530                                                                                                  vk::VkDevice                                                           device,
531                                                                                                  vk::VkImage                                                            image,
532                                                                                                  NativeHandle&                                                          nativeHandle,
533                                                                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
534                                                                                                  bool                                                                           dedicated)
535 {
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));
541
542         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
543 }
544
545 de::MovePtr<Resource> importResource (const vk::DeviceInterface&                                vkd,
546                                                                           vk::VkDevice                                                          device,
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,
553                                                                           bool                                                                          dedicated)
554 {
555         if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
556         {
557                 const vk::VkExtent3D                            extent                                  =
558                 {
559                         (deUint32)resourceDesc.size.x(),
560                         de::max(1u, (deUint32)resourceDesc.size.y()),
561                         de::max(1u, (deUint32)resourceDesc.size.z())
562                 };
563                 const vk::VkImageSubresourceRange       subresourceRange                =
564                 {
565                         resourceDesc.imageAspect,
566                         0u,
567                         1u,
568                         0u,
569                         1u
570                 };
571                 const vk::VkImageSubresourceLayers      subresourceLayers               =
572                 {
573                         resourceDesc.imageAspect,
574                         0u,
575                         0u,
576                         1u
577                 };
578                 const vk:: VkExternalMemoryImageCreateInfoKHR externalInfo =
579                 {
580                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
581                         DE_NULL,
582                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
583                 };
584                 const vk::VkImageCreateInfo                     createInfo                              =
585                 {
586                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
587                         &externalInfo,
588                         0u,
589
590                         resourceDesc.imageType,
591                         resourceDesc.imageFormat,
592                         extent,
593                         1u,
594                         1u,
595                         vk::VK_SAMPLE_COUNT_1_BIT,
596                         vk::VK_IMAGE_TILING_OPTIMAL,
597                         readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
598                         vk::VK_SHARING_MODE_EXCLUSIVE,
599
600                         (deUint32)queueFamilyIndices.size(),
601                         &queueFamilyIndices[0],
602                         vk::VK_IMAGE_LAYOUT_UNDEFINED
603                 };
604
605                 vk::Move<vk::VkImage>                   image           = vk::createImage(vkd, device, &createInfo);
606                 de::MovePtr<vk::Allocation>             allocation      = importAndBindMemory(vkd, device, *image, nativeHandle, externalType, dedicated);
607
608                 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
609         }
610         else
611         {
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    =
616                 {
617                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
618                         DE_NULL,
619                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
620                 };
621                 const vk::VkBufferCreateInfo                                    createInfo              =
622                 {
623                         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
624                         &externalInfo,
625                         0u,
626
627                         size,
628                         usage,
629                         vk::VK_SHARING_MODE_EXCLUSIVE,
630                         (deUint32)queueFamilyIndices.size(),
631                         &queueFamilyIndices[0]
632                 };
633                 vk::Move<vk::VkBuffer>          buffer          = vk::createBuffer(vkd, device, &createInfo);
634                 de::MovePtr<vk::Allocation>     allocation      = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType, dedicated);
635
636                 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
637         }
638 }
639
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)
646 {
647         const vk::VkPipelineStageFlags  srcStageMask            = writeSync.stageMask;
648         const vk::VkAccessFlags                 srcAccessMask           = writeSync.accessMask;
649
650         const vk::VkPipelineStageFlags  dstStageMask            = readSync.stageMask;
651         const vk::VkAccessFlags                 dstAccessMask           = readSync.accessMask;
652
653         const vk::VkDependencyFlags             dependencyFlags         = 0;
654
655         if (resource.getType() == RESOURCE_TYPE_IMAGE)
656         {
657                 const vk::VkImageMemoryBarrier  barrier                         =
658                 {
659                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
660                         DE_NULL,
661
662                         srcAccessMask,
663                         dstAccessMask,
664
665                         writeSync.imageLayout,
666                         readSync.imageLayout,
667
668                         writeQueueFamilyIndex,
669                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
670
671                         resource.getImage().handle,
672                         resource.getImage().subresourceRange
673                 };
674
675                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
676         }
677         else
678         {
679                 const vk::VkBufferMemoryBarrier barrier                         =
680                 {
681                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
682                         DE_NULL,
683
684                         srcAccessMask,
685                         dstAccessMask,
686
687                         writeQueueFamilyIndex,
688                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
689
690                         resource.getBuffer().handle,
691                         0u,
692                         VK_WHOLE_SIZE
693                 };
694
695                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
696         }
697 }
698
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)
705 {
706         const vk::VkPipelineStageFlags  srcStageMask            = readSync.stageMask;
707         const vk::VkAccessFlags                 srcAccessMask           = readSync.accessMask;
708
709         const vk::VkPipelineStageFlags  dstStageMask            = readSync.stageMask;
710         const vk::VkAccessFlags                 dstAccessMask           = readSync.accessMask;
711
712         const vk::VkDependencyFlags             dependencyFlags         = 0;
713
714         if (resource.getType() == RESOURCE_TYPE_IMAGE)
715         {
716                 const vk::VkImageMemoryBarrier  barrier                         =
717                 {
718                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
719                         DE_NULL,
720
721                         srcAccessMask,
722                         dstAccessMask,
723
724                         writeSync.imageLayout,
725                         readSync.imageLayout,
726
727                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
728                         readQueueFamilyIndex,
729
730                         resource.getImage().handle,
731                         resource.getImage().subresourceRange
732                 };
733
734                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
735         }
736         else
737         {
738                 const vk::VkBufferMemoryBarrier barrier                         =
739                 {
740                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
741                         DE_NULL,
742
743                         srcAccessMask,
744                         dstAccessMask,
745
746                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
747                         readQueueFamilyIndex,
748
749                         resource.getBuffer().handle,
750                         0u,
751                         VK_WHOLE_SIZE
752                 };
753
754                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
755         }
756 }
757
758 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
759 {
760         std::vector<deUint32> indices (properties.size(), 0);
761
762         for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
763                 indices[ndx] = ndx;
764
765         return indices;
766 }
767
768 class SharingTestInstance : public TestInstance
769 {
770 public:
771                                                                                                                 SharingTestInstance             (Context&       context,
772                                                                                                                                                                  TestConfig     config);
773
774         virtual tcu::TestStatus                                                         iterate                                 (void);
775
776 private:
777         const TestConfig                                                                        m_config;
778         const de::UniquePtr<OperationSupport>                           m_supportWriteOp;
779         const de::UniquePtr<OperationSupport>                           m_supportReadOp;
780
781         const vk::Unique<vk::VkInstance>                                        m_instanceA;
782
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;
787
788         const vk::Unique<vk::VkDevice>                                          m_deviceA;
789         const vk::DeviceDriver                                                          m_vkdA;
790
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;
798
799         const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR      m_semaphoreHandleType;
800         const vk::VkExternalMemoryHandleTypeFlagBitsKHR         m_memoryHandleType;
801
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;
805         size_t                                                                                          m_queueANdx;
806         size_t                                                                                          m_queueBNdx;
807 };
808
809 SharingTestInstance::SharingTestInstance (Context&              context,
810                                                                                   TestConfig    config)
811         : TestInstance                          (context)
812         , m_config                                      (config)
813         , m_supportWriteOp                      (makeOperationSupport(config.writeOp, config.resource))
814         , m_supportReadOp                       (makeOperationSupport(config.readOp, config.resource))
815
816         , m_instanceA                           (createInstance(context.getPlatformInterface()))
817
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)
824
825         , m_instanceB                           (createInstance(context.getPlatformInterface()))
826
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)
833
834         , m_semaphoreHandleType         (m_config.semaphoreHandleType)
835         , m_memoryHandleType            (m_config.memoryHandleType)
836
837         , m_resultCollector                     (context.getTestContext().getLog())
838         , m_queueANdx                           (0)
839         , m_queueBNdx                           (0)
840 {
841         TestLog& log = m_context.getTestContext().getLog();
842
843         // Check resource support
844         if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
845         {
846                 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR    externalInfo            =
847                 {
848                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
849                         DE_NULL,
850                         m_memoryHandleType
851                 };
852                 const vk::VkPhysicalDeviceImageFormatInfo2KHR   imageFormatInfo         =
853                 {
854                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
855                         &externalInfo,
856                         m_config.resource.imageFormat,
857                         m_config.resource.imageType,
858                         vk::VK_IMAGE_TILING_OPTIMAL,
859                         m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
860                         0u
861                 };
862                 vk::VkExternalImageFormatPropertiesKHR                  externalProperties      =
863                 {
864                         vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
865                         DE_NULL,
866                         { 0u, 0u, 0u }
867                 };
868                 vk::VkImageFormatProperties2KHR                                 formatProperties        =
869                 {
870                         vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
871                         &externalProperties,
872                         {
873                                 { 0u, 0u, 0u },
874                                 0u,
875                                 0u,
876                                 0u,
877                                 0u,
878                         }
879                 };
880
881                 {
882                         const vk::VkResult res = m_vkiA.getPhysicalDeviceImageFormatProperties2KHR(m_physicalDeviceA, &imageFormatInfo, &formatProperties);
883
884                         if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
885                                 TCU_THROW(NotSupportedError, "Image format not supported");
886
887                         VK_CHECK(res); // Check other errors
888                 }
889
890                 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
891
892                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
893                         TCU_THROW(NotSupportedError, "Exporting image resource not supported");
894
895                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
896                         TCU_THROW(NotSupportedError, "Importing image resource not supported");
897         }
898         else
899         {
900                 const vk::VkPhysicalDeviceExternalBufferInfoKHR info    =
901                 {
902                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
903                         DE_NULL,
904
905                         0u,
906                         m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
907                         m_memoryHandleType
908                 };
909                 vk::VkExternalBufferPropertiesKHR                               properties                      =
910                 {
911                         vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
912                         DE_NULL,
913                         { 0u, 0u, 0u}
914                 };
915                 m_vkiA.getPhysicalDeviceExternalBufferPropertiesKHR(m_physicalDeviceA, &info, &properties);
916
917                 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
918
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");
922         }
923
924         // Check semaphore support
925         {
926                 const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR      info            =
927                 {
928                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
929                         DE_NULL,
930                         m_semaphoreHandleType
931                 };
932                 vk::VkExternalSemaphorePropertiesKHR                            properties;
933
934                 m_vkiA.getPhysicalDeviceExternalSemaphorePropertiesKHR(m_physicalDeviceA, &info, &properties);
935
936                 log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
937
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");
941         }
942 }
943
944 tcu::TestStatus SharingTestInstance::iterate (void)
945 {
946         TestLog&                                                                log                                     (m_context.getTestContext().getLog());
947
948         const deUint32                                                  queueFamilyA            = (deUint32)m_queueANdx;
949         const deUint32                                                  queueFamilyB            = (deUint32)m_queueBNdx;
950
951         const tcu::ScopedLogSection                             queuePairSection        (log,
952                                                                                                                                         "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB),
953                                                                                                                                         "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB));
954
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));
957
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));
959
960         NativeHandle                                                    nativeMemoryHandle;
961         getMemoryNative(m_vkdA, *m_deviceA, resourceA->getMemory(), m_memoryHandleType, nativeMemoryHandle);
962
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));
964
965         try
966         {
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);
973
974                 if (!checkQueueFlags(m_queueFamiliesA[m_queueANdx].queueFlags , m_supportWriteOp->getQueueFlags(operationContextA)))
975                         TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
976
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);
983
984                 if (!checkQueueFlags(m_queueFamiliesB[m_queueBNdx].queueFlags , m_supportReadOp->getQueueFlags(operationContextB)))
985                         TCU_THROW(NotSupportedError, "Operation not supported by the destination queue");
986
987                 const de::UniquePtr<Operation>                  writeOp                         (m_supportWriteOp->build(operationContextA, *resourceA));
988                 const de::UniquePtr<Operation>                  readOp                          (m_supportReadOp->build(operationContextB, *resourceB));
989
990                 const SyncInfo                                                  writeSync                       = writeOp->getSyncInfo();
991                 const SyncInfo                                                  readSync                        = readOp->getSyncInfo();
992
993                 beginCommandBuffer(m_vkdA, *commandBufferA);
994                 writeOp->recordCommands(*commandBufferA);
995                 recordWriteBarrier(m_vkdA, *commandBufferA, *resourceA, writeSync, queueFamilyA, readSync);
996                 endCommandBuffer(m_vkdA, *commandBufferA);
997
998                 beginCommandBuffer(m_vkdB, *commandBufferB);
999                 recordReadBarrier(m_vkdB, *commandBufferB, *resourceB, writeSync, readSync, queueFamilyB);
1000                 readOp->recordCommands(*commandBufferB);
1001                 endCommandBuffer(m_vkdB, *commandBufferB);
1002
1003                 {
1004                         const vk::VkCommandBuffer       commandBuffer   = *commandBufferA;
1005                         const vk::VkSemaphore           semaphore               = *semaphoreA;
1006                         const vk::VkSubmitInfo          submitInfo              =
1007                         {
1008                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1009                                 DE_NULL,
1010
1011                                 0u,
1012                                 DE_NULL,
1013                                 DE_NULL,
1014
1015                                 1u,
1016                                 &commandBuffer,
1017                                 1u,
1018                                 &semaphore
1019                         };
1020
1021                         VK_CHECK(m_vkdA.queueSubmit(queueA, 1u, &submitInfo, DE_NULL));
1022
1023                         {
1024                                 NativeHandle    nativeSemaphoreHandle;
1025
1026                                 getSemaphoreNative(m_vkdA, *m_deviceA, *semaphoreA, m_semaphoreHandleType, nativeSemaphoreHandle);
1027                                 importSemaphore(m_vkdB, *m_deviceB, *semaphoreB, m_semaphoreHandleType, nativeSemaphoreHandle, 0u);
1028                         }
1029                 }
1030                 {
1031                         const vk::VkCommandBuffer               commandBuffer   = *commandBufferB;
1032                         const vk::VkSemaphore                   semaphore               = *semaphoreB;
1033                         const vk::VkPipelineStageFlags  dstStage                = readSync.stageMask;
1034                         const vk::VkSubmitInfo                  submitInfo              =
1035                         {
1036                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1037                                 DE_NULL,
1038
1039                                 1u,
1040                                 &semaphore,
1041                                 &dstStage,
1042
1043                                 1u,
1044                                 &commandBuffer,
1045                                 0u,
1046                                 DE_NULL,
1047                         };
1048
1049                         VK_CHECK(m_vkdB.queueSubmit(queueB, 1u, &submitInfo, DE_NULL));
1050                 }
1051
1052                 VK_CHECK(m_vkdA.queueWaitIdle(queueA));
1053                 VK_CHECK(m_vkdB.queueWaitIdle(queueB));
1054
1055                 {
1056                         const Data      expected        = writeOp->getData();
1057                         const Data      actual          = readOp->getData();
1058
1059                         DE_ASSERT(expected.size == actual.size);
1060
1061                         if (0 != deMemCmp(expected.data, actual.data, expected.size))
1062                         {
1063                                 const size_t            maxBytesLogged  = 256;
1064                                 std::ostringstream      expectedData;
1065                                 std::ostringstream      actualData;
1066                                 size_t                          byteNdx                 = 0;
1067
1068                                 // Find first byte difference
1069                                 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1070                                 {
1071                                         // Nothing
1072                                 }
1073
1074                                 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1075
1076                                 // Log 8 previous bytes before the first incorrect byte
1077                                 if (byteNdx > 8)
1078                                 {
1079                                         expectedData << "... ";
1080                                         actualData << "... ";
1081
1082                                         byteNdx -= 8;
1083                                 }
1084                                 else
1085                                         byteNdx = 0;
1086
1087                                 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1088                                 {
1089                                         expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1090                                         actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1091                                 }
1092
1093                                 if (expected.size > byteNdx)
1094                                 {
1095                                         expectedData << "...";
1096                                         actualData << "...";
1097                                 }
1098
1099                                 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1100                                 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1101
1102                                 m_resultCollector.fail("Memory contents don't match");
1103                         }
1104                 }
1105         }
1106         catch (const tcu::NotSupportedError& error)
1107         {
1108                 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1109         }
1110         catch (const tcu::TestError& error)
1111         {
1112                 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1113         }
1114
1115         // Move to next queue
1116         {
1117                 m_queueBNdx++;
1118
1119                 if (m_queueBNdx >= m_queueFamiliesB.size())
1120                 {
1121                         m_queueANdx++;
1122
1123                         if (m_queueANdx >= m_queueFamiliesA.size())
1124                         {
1125                                 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1126                         }
1127                         else
1128                         {
1129                                 m_queueBNdx = 0;
1130
1131                                 return tcu::TestStatus::incomplete();
1132                         }
1133                 }
1134                 else
1135                         return tcu::TestStatus::incomplete();
1136         }
1137 }
1138
1139 struct Progs
1140 {
1141         void init (vk::SourceCollections& dst, TestConfig config) const
1142         {
1143                 const de::UniquePtr<OperationSupport>   readOp  (makeOperationSupport(config.readOp, config.resource));
1144                 const de::UniquePtr<OperationSupport>   writeOp (makeOperationSupport(config.writeOp, config.resource));
1145
1146                 readOp->initPrograms(dst);
1147                 writeOp->initPrograms(dst);
1148         }
1149 };
1150
1151 } // anonymous
1152
1153 tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
1154 {
1155         const struct
1156         {
1157                 vk::VkExternalMemoryHandleTypeFlagBitsKHR               memoryType;
1158                 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR    semaphoreType;
1159                 const char*                                                                             nameSuffix;
1160         } cases[] =
1161         {
1162                 {
1163                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1164                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1165                         "_fd"
1166                 },
1167                 {
1168                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1169                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR,
1170                         "_fence_fd"
1171                 },
1172                 {
1173                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1174                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1175                         "_win32_kmt"
1176                 },
1177                 {
1178                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1179                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1180                         "_win32"
1181                 },
1182         };
1183         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", ""));
1184
1185         for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
1186         {
1187                 const bool                                              dedicated               (dedicatedNdx == 1);
1188                 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup  (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
1189
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)
1192                 {
1193                         const OperationName     writeOp         = s_writeOps[writeOpNdx];
1194                         const OperationName     readOp          = s_readOps[readOpNdx];
1195                         const std::string       opGroupName     = getOperationName(writeOp) + "_" + getOperationName(readOp);
1196                         bool                            empty           = true;
1197
1198                         de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1199
1200                         for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resources); ++resourceNdx)
1201                         {
1202                                 const ResourceDescription&      resource        = s_resources[resourceNdx];
1203
1204                                 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1205                                 {
1206                                         std::string     name= getResourceName(resource) + cases[caseNdx].nameSuffix;
1207
1208                                         if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1209                                         {
1210                                                 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryType, cases[caseNdx].semaphoreType, dedicated);
1211
1212                                                 opGroup->addChild(new InstanceFactory1<SharingTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE,  name, "", Progs(), config));
1213                                                 empty = false;
1214                                         }
1215                                 }
1216                         }
1217
1218                         if (!empty)
1219                                 dedicatedGroup->addChild(opGroup.release());
1220                 }
1221
1222                 group->addChild(dedicatedGroup.release());
1223         }
1224
1225         return group.release();
1226 }
1227
1228 } // synchronization
1229 } // vkt