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