Fix regressions in synchronization tests for dedicated allocations
[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                 memoryRequirements = requirements.memoryRequirements;
437         }
438         else
439         {
440                 vkd.getImageMemoryRequirements(device, image, &memoryRequirements);
441         }
442
443         vk::Move<vk::VkDeviceMemory> memory = allocateExportableMemory(vkd, device, memoryRequirements, externalType, dedicated ? image : (vk::VkImage)0, exportedMemoryTypeIndex);
444         VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
445
446         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
447 }
448
449 de::MovePtr<Resource> createResource (const vk::DeviceInterface&                                vkd,
450                                                                           vk::VkDevice                                                          device,
451                                                                           const ResourceDescription&                            resourceDesc,
452                                                                           const std::vector<deUint32>&                          queueFamilyIndices,
453                                                                           const OperationSupport&                                       readOp,
454                                                                           const OperationSupport&                                       writeOp,
455                                                                           vk::VkExternalMemoryHandleTypeFlagBitsKHR     externalType,
456                                                                           deUint32&                                                                     exportedMemoryTypeIndex,
457                                                                           bool                                                                          dedicated,
458                                                                           bool                                                                          getMemReq2Supported)
459 {
460         if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
461         {
462                 const vk::VkExtent3D                            extent                                  =
463                 {
464                         (deUint32)resourceDesc.size.x(),
465                         de::max(1u, (deUint32)resourceDesc.size.y()),
466                         de::max(1u, (deUint32)resourceDesc.size.z())
467                 };
468                 const vk::VkImageSubresourceRange       subresourceRange                =
469                 {
470                         resourceDesc.imageAspect,
471                         0u,
472                         1u,
473                         0u,
474                         1u
475                 };
476                 const vk::VkImageSubresourceLayers      subresourceLayers               =
477                 {
478                         resourceDesc.imageAspect,
479                         0u,
480                         0u,
481                         1u
482                 };
483                 const vk::VkExternalMemoryImageCreateInfoKHR externalInfo =
484                 {
485                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
486                         DE_NULL,
487                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
488                 };
489                 const vk::VkImageCreateInfo                     createInfo                              =
490                 {
491                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
492                         &externalInfo,
493                         0u,
494
495                         resourceDesc.imageType,
496                         resourceDesc.imageFormat,
497                         extent,
498                         1u,
499                         1u,
500                         vk::VK_SAMPLE_COUNT_1_BIT,
501                         vk::VK_IMAGE_TILING_OPTIMAL,
502                         readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
503                         vk::VK_SHARING_MODE_EXCLUSIVE,
504
505                         (deUint32)queueFamilyIndices.size(),
506                         &queueFamilyIndices[0],
507                         vk::VK_IMAGE_LAYOUT_UNDEFINED
508                 };
509
510                 vk::Move<vk::VkImage>                   image           = vk::createImage(vkd, device, &createInfo);
511                 de::MovePtr<vk::Allocation>             allocation      = allocateAndBindMemory(vkd, device, *image, externalType, exportedMemoryTypeIndex, dedicated, getMemReq2Supported);
512
513                 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
514         }
515         else
516         {
517                 const vk::VkDeviceSize                                                  offset                  = 0u;
518                 const vk::VkDeviceSize                                                  size                    = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
519                 const vk::VkBufferUsageFlags                                    usage                   = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
520                 const vk:: VkExternalMemoryBufferCreateInfoKHR  externalInfo    =
521                 {
522                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
523                         DE_NULL,
524                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
525                 };
526                 const vk::VkBufferCreateInfo                                    createInfo              =
527                 {
528                         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
529                         &externalInfo,
530                         0u,
531
532                         size,
533                         usage,
534                         vk::VK_SHARING_MODE_EXCLUSIVE,
535                         (deUint32)queueFamilyIndices.size(),
536                         &queueFamilyIndices[0]
537                 };
538                 vk::Move<vk::VkBuffer>          buffer          = vk::createBuffer(vkd, device, &createInfo);
539                 de::MovePtr<vk::Allocation>     allocation      = allocateAndBindMemory(vkd, device, *buffer, externalType, exportedMemoryTypeIndex, dedicated, getMemReq2Supported);
540
541                 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
542         }
543 }
544
545 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface&                                     vkd,
546                                                                                                  vk::VkDevice                                                           device,
547                                                                                                  vk::VkBuffer                                                           buffer,
548                                                                                                  NativeHandle&                                                          nativeHandle,
549                                                                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
550                                                                                                  deUint32                                                                       exportedMemoryTypeIndex,
551                                                                                                  bool                                                                           dedicated)
552 {
553         const vk::VkMemoryRequirements  requirements    = vk::getBufferMemoryRequirements(vkd, device, buffer);
554         vk::Move<vk::VkDeviceMemory>    memory                  = dedicated
555                                                                                                         ? importDedicatedMemory(vkd, device, buffer, requirements, externalType, exportedMemoryTypeIndex, nativeHandle)
556                                                                                                         : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle);
557
558         VK_CHECK(vkd.bindBufferMemory(device, buffer, *memory, 0u));
559
560         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
561 }
562
563 de::MovePtr<vk::Allocation> importAndBindMemory (const vk::DeviceInterface&                                     vkd,
564                                                                                                  vk::VkDevice                                                           device,
565                                                                                                  vk::VkImage                                                            image,
566                                                                                                  NativeHandle&                                                          nativeHandle,
567                                                                                                  vk::VkExternalMemoryHandleTypeFlagBitsKHR      externalType,
568                                                                                                  deUint32                                                                       exportedMemoryTypeIndex,
569                                                                                                  bool                                                                           dedicated)
570 {
571         const vk::VkMemoryRequirements  requirements    = vk::getImageMemoryRequirements(vkd, device, image);
572         vk::Move<vk::VkDeviceMemory>    memory                  = dedicated
573                                                                                                         ? importDedicatedMemory(vkd, device, image, requirements, externalType, exportedMemoryTypeIndex, nativeHandle)
574                                                                                                         : importMemory(vkd, device, requirements, externalType, exportedMemoryTypeIndex, nativeHandle);
575         VK_CHECK(vkd.bindImageMemory(device, image, *memory, 0u));
576
577         return de::MovePtr<vk::Allocation>(new SimpleAllocation(vkd, device, memory.disown()));
578 }
579
580 de::MovePtr<Resource> importResource (const vk::DeviceInterface&                                vkd,
581                                                                           vk::VkDevice                                                          device,
582                                                                           const ResourceDescription&                            resourceDesc,
583                                                                           const std::vector<deUint32>&                          queueFamilyIndices,
584                                                                           const OperationSupport&                                       readOp,
585                                                                           const OperationSupport&                                       writeOp,
586                                                                           NativeHandle&                                                         nativeHandle,
587                                                                           vk::VkExternalMemoryHandleTypeFlagBitsKHR     externalType,
588                                                                           deUint32                                                                      exportedMemoryTypeIndex,
589                                                                           bool                                                                          dedicated)
590 {
591         if (resourceDesc.type == RESOURCE_TYPE_IMAGE)
592         {
593                 const vk::VkExtent3D                            extent                                  =
594                 {
595                         (deUint32)resourceDesc.size.x(),
596                         de::max(1u, (deUint32)resourceDesc.size.y()),
597                         de::max(1u, (deUint32)resourceDesc.size.z())
598                 };
599                 const vk::VkImageSubresourceRange       subresourceRange                =
600                 {
601                         resourceDesc.imageAspect,
602                         0u,
603                         1u,
604                         0u,
605                         1u
606                 };
607                 const vk::VkImageSubresourceLayers      subresourceLayers               =
608                 {
609                         resourceDesc.imageAspect,
610                         0u,
611                         0u,
612                         1u
613                 };
614                 const vk:: VkExternalMemoryImageCreateInfoKHR externalInfo =
615                 {
616                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
617                         DE_NULL,
618                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
619                 };
620                 const vk::VkImageCreateInfo                     createInfo                              =
621                 {
622                         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
623                         &externalInfo,
624                         0u,
625
626                         resourceDesc.imageType,
627                         resourceDesc.imageFormat,
628                         extent,
629                         1u,
630                         1u,
631                         vk::VK_SAMPLE_COUNT_1_BIT,
632                         vk::VK_IMAGE_TILING_OPTIMAL,
633                         readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags(),
634                         vk::VK_SHARING_MODE_EXCLUSIVE,
635
636                         (deUint32)queueFamilyIndices.size(),
637                         &queueFamilyIndices[0],
638                         vk::VK_IMAGE_LAYOUT_UNDEFINED
639                 };
640
641                 vk::Move<vk::VkImage>                   image           = vk::createImage(vkd, device, &createInfo);
642                 de::MovePtr<vk::Allocation>             allocation      = importAndBindMemory(vkd, device, *image, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
643
644                 return de::MovePtr<Resource>(new Resource(image, allocation, extent, resourceDesc.imageType, resourceDesc.imageFormat, subresourceRange, subresourceLayers));
645         }
646         else
647         {
648                 const vk::VkDeviceSize                                                  offset                  = 0u;
649                 const vk::VkDeviceSize                                                  size                    = static_cast<vk::VkDeviceSize>(resourceDesc.size.x());
650                 const vk::VkBufferUsageFlags                                    usage                   = readOp.getResourceUsageFlags() | writeOp.getResourceUsageFlags();
651                 const vk:: VkExternalMemoryBufferCreateInfoKHR  externalInfo    =
652                 {
653                         vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
654                         DE_NULL,
655                         (vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
656                 };
657                 const vk::VkBufferCreateInfo                                    createInfo              =
658                 {
659                         vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
660                         &externalInfo,
661                         0u,
662
663                         size,
664                         usage,
665                         vk::VK_SHARING_MODE_EXCLUSIVE,
666                         (deUint32)queueFamilyIndices.size(),
667                         &queueFamilyIndices[0]
668                 };
669                 vk::Move<vk::VkBuffer>          buffer          = vk::createBuffer(vkd, device, &createInfo);
670                 de::MovePtr<vk::Allocation>     allocation      = importAndBindMemory(vkd, device, *buffer, nativeHandle, externalType, exportedMemoryTypeIndex, dedicated);
671
672                 return de::MovePtr<Resource>(new Resource(resourceDesc.type, buffer, allocation, offset, size));
673         }
674 }
675
676 void recordWriteBarrier (const vk::DeviceInterface&     vkd,
677                                                  vk::VkCommandBuffer            commandBuffer,
678                                                  const Resource&                        resource,
679                                                  const SyncInfo&                        writeSync,
680                                                  deUint32                                       writeQueueFamilyIndex,
681                                                  const SyncInfo&                        readSync)
682 {
683         const vk::VkPipelineStageFlags  srcStageMask            = writeSync.stageMask;
684         const vk::VkAccessFlags                 srcAccessMask           = writeSync.accessMask;
685
686         const vk::VkPipelineStageFlags  dstStageMask            = readSync.stageMask;
687         const vk::VkAccessFlags                 dstAccessMask           = readSync.accessMask;
688
689         const vk::VkDependencyFlags             dependencyFlags         = 0;
690
691         if (resource.getType() == RESOURCE_TYPE_IMAGE)
692         {
693                 const vk::VkImageMemoryBarrier  barrier                         =
694                 {
695                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
696                         DE_NULL,
697
698                         srcAccessMask,
699                         dstAccessMask,
700
701                         writeSync.imageLayout,
702                         readSync.imageLayout,
703
704                         writeQueueFamilyIndex,
705                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
706
707                         resource.getImage().handle,
708                         resource.getImage().subresourceRange
709                 };
710
711                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
712         }
713         else
714         {
715                 const vk::VkBufferMemoryBarrier barrier                         =
716                 {
717                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
718                         DE_NULL,
719
720                         srcAccessMask,
721                         dstAccessMask,
722
723                         writeQueueFamilyIndex,
724                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
725
726                         resource.getBuffer().handle,
727                         0u,
728                         VK_WHOLE_SIZE
729                 };
730
731                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
732         }
733 }
734
735 void recordReadBarrier (const vk::DeviceInterface&      vkd,
736                                                 vk::VkCommandBuffer                     commandBuffer,
737                                                 const Resource&                         resource,
738                                                 const SyncInfo&                         writeSync,
739                                                 const SyncInfo&                         readSync,
740                                                 deUint32                                        readQueueFamilyIndex)
741 {
742         const vk::VkPipelineStageFlags  srcStageMask            = readSync.stageMask;
743         const vk::VkAccessFlags                 srcAccessMask           = readSync.accessMask;
744
745         const vk::VkPipelineStageFlags  dstStageMask            = readSync.stageMask;
746         const vk::VkAccessFlags                 dstAccessMask           = readSync.accessMask;
747
748         const vk::VkDependencyFlags             dependencyFlags         = 0;
749
750         if (resource.getType() == RESOURCE_TYPE_IMAGE)
751         {
752                 const vk::VkImageMemoryBarrier  barrier                         =
753                 {
754                         vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
755                         DE_NULL,
756
757                         srcAccessMask,
758                         dstAccessMask,
759
760                         writeSync.imageLayout,
761                         readSync.imageLayout,
762
763                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
764                         readQueueFamilyIndex,
765
766                         resource.getImage().handle,
767                         resource.getImage().subresourceRange
768                 };
769
770                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, (const vk::VkImageMemoryBarrier*)&barrier);
771         }
772         else
773         {
774                 const vk::VkBufferMemoryBarrier barrier                         =
775                 {
776                         vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
777                         DE_NULL,
778
779                         srcAccessMask,
780                         dstAccessMask,
781
782                         VK_QUEUE_FAMILY_EXTERNAL_KHR,
783                         readQueueFamilyIndex,
784
785                         resource.getBuffer().handle,
786                         0u,
787                         VK_WHOLE_SIZE
788                 };
789
790                 vkd.cmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 1u, (const vk::VkBufferMemoryBarrier*)&barrier, 0u, (const vk::VkImageMemoryBarrier*)DE_NULL);
791         }
792 }
793
794 std::vector<deUint32> getFamilyIndices (const std::vector<vk::VkQueueFamilyProperties>& properties)
795 {
796         std::vector<deUint32> indices (properties.size(), 0);
797
798         for (deUint32 ndx = 0; ndx < properties.size(); ndx++)
799                 indices[ndx] = ndx;
800
801         return indices;
802 }
803
804 class SharingTestInstance : public TestInstance
805 {
806 public:
807                                                                                                                 SharingTestInstance             (Context&       context,
808                                                                                                                                                                  TestConfig     config);
809
810         virtual tcu::TestStatus                                                         iterate                                 (void);
811
812 private:
813         const TestConfig                                                                        m_config;
814         const de::UniquePtr<OperationSupport>                           m_supportWriteOp;
815         const de::UniquePtr<OperationSupport>                           m_supportReadOp;
816
817         const vk::Unique<vk::VkInstance>                                        m_instanceA;
818
819         const vk::InstanceDriver                                                        m_vkiA;
820         const vk::VkPhysicalDevice                                                      m_physicalDeviceA;
821         const std::vector<vk::VkQueueFamilyProperties>          m_queueFamiliesA;
822         const std::vector<deUint32>                                                     m_queueFamilyIndicesA;
823
824         const bool                                                                                      m_getMemReq2Supported;
825
826         const vk::Unique<vk::VkDevice>                                          m_deviceA;
827         const vk::DeviceDriver                                                          m_vkdA;
828
829         const vk::Unique<vk::VkInstance>                                        m_instanceB;
830         const vk::InstanceDriver                                                        m_vkiB;
831         const vk::VkPhysicalDevice                                                      m_physicalDeviceB;
832         const std::vector<vk::VkQueueFamilyProperties>          m_queueFamiliesB;
833         const std::vector<deUint32>                                                     m_queueFamilyIndicesB;
834         const vk::Unique<vk::VkDevice>                                          m_deviceB;
835         const vk::DeviceDriver                                                          m_vkdB;
836
837         const vk::VkExternalSemaphoreHandleTypeFlagBitsKHR      m_semaphoreHandleType;
838         const vk::VkExternalMemoryHandleTypeFlagBitsKHR         m_memoryHandleType;
839
840         // \todo Should this be moved to the group same way as in the other tests?
841         PipelineCacheData                                                                       m_pipelineCacheData;
842         tcu::ResultCollector                                                            m_resultCollector;
843         size_t                                                                                          m_queueANdx;
844         size_t                                                                                          m_queueBNdx;
845 };
846
847 SharingTestInstance::SharingTestInstance (Context&              context,
848                                                                                   TestConfig    config)
849         : TestInstance                          (context)
850         , m_config                                      (config)
851         , m_supportWriteOp                      (makeOperationSupport(config.writeOp, config.resource))
852         , m_supportReadOp                       (makeOperationSupport(config.readOp, config.resource))
853
854         , m_instanceA                           (createInstance(context.getPlatformInterface()))
855
856         , m_vkiA                                        (context.getPlatformInterface(), *m_instanceA)
857         , m_physicalDeviceA                     (getPhysicalDevice(m_vkiA, *m_instanceA, context.getTestContext().getCommandLine()))
858         , m_queueFamiliesA                      (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiA, m_physicalDeviceA))
859         , m_queueFamilyIndicesA         (getFamilyIndices(m_queueFamiliesA))
860         , m_getMemReq2Supported         (de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), "VK_KHR_get_memory_requirements2"))
861         , m_deviceA                                     (createDevice(m_vkiA, m_physicalDeviceA, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported))
862         , m_vkdA                                        (m_vkiA, *m_deviceA)
863
864         , m_instanceB                           (createInstance(context.getPlatformInterface()))
865
866         , m_vkiB                                        (context.getPlatformInterface(), *m_instanceB)
867         , m_physicalDeviceB                     (getPhysicalDevice(m_vkiB, *m_instanceB, getDeviceId(m_vkiA, m_physicalDeviceA)))
868         , m_queueFamiliesB                      (vk::getPhysicalDeviceQueueFamilyProperties(m_vkiB, m_physicalDeviceB))
869         , m_queueFamilyIndicesB         (getFamilyIndices(m_queueFamiliesB))
870         , m_deviceB                                     (createDevice(m_vkiB, m_physicalDeviceB, m_config.memoryHandleType, m_config.semaphoreHandleType, m_config.dedicated, m_getMemReq2Supported))
871         , m_vkdB                                        (m_vkiB, *m_deviceB)
872
873         , m_semaphoreHandleType         (m_config.semaphoreHandleType)
874         , m_memoryHandleType            (m_config.memoryHandleType)
875
876         , m_resultCollector                     (context.getTestContext().getLog())
877         , m_queueANdx                           (0)
878         , m_queueBNdx                           (0)
879 {
880         TestLog& log = m_context.getTestContext().getLog();
881
882         // Check resource support
883         if (m_config.resource.type == RESOURCE_TYPE_IMAGE)
884         {
885                 const vk::VkPhysicalDeviceExternalImageFormatInfoKHR    externalInfo            =
886                 {
887                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR,
888                         DE_NULL,
889                         m_memoryHandleType
890                 };
891                 const vk::VkPhysicalDeviceImageFormatInfo2KHR   imageFormatInfo         =
892                 {
893                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR,
894                         &externalInfo,
895                         m_config.resource.imageFormat,
896                         m_config.resource.imageType,
897                         vk::VK_IMAGE_TILING_OPTIMAL,
898                         m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
899                         0u
900                 };
901                 vk::VkExternalImageFormatPropertiesKHR                  externalProperties      =
902                 {
903                         vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
904                         DE_NULL,
905                         { 0u, 0u, 0u }
906                 };
907                 vk::VkImageFormatProperties2KHR                                 formatProperties        =
908                 {
909                         vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR,
910                         &externalProperties,
911                         {
912                                 { 0u, 0u, 0u },
913                                 0u,
914                                 0u,
915                                 0u,
916                                 0u,
917                         }
918                 };
919
920                 {
921                         const vk::VkResult res = m_vkiA.getPhysicalDeviceImageFormatProperties2KHR(m_physicalDeviceA, &imageFormatInfo, &formatProperties);
922
923                         if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
924                                 TCU_THROW(NotSupportedError, "Image format not supported");
925
926                         VK_CHECK(res); // Check other errors
927                 }
928
929                 log << TestLog::Message << "External image format properties: " << imageFormatInfo << "\n"<< externalProperties << TestLog::EndMessage;
930
931                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0)
932                         TCU_THROW(NotSupportedError, "Exporting image resource not supported");
933
934                 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
935                         TCU_THROW(NotSupportedError, "Importing image resource not supported");
936
937                 if (!m_config.dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
938                 {
939                         TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
940                 }
941         }
942         else
943         {
944                 const vk::VkPhysicalDeviceExternalBufferInfoKHR info    =
945                 {
946                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO_KHR,
947                         DE_NULL,
948
949                         0u,
950                         m_supportReadOp->getResourceUsageFlags() | m_supportWriteOp->getResourceUsageFlags(),
951                         m_memoryHandleType
952                 };
953                 vk::VkExternalBufferPropertiesKHR                               properties                      =
954                 {
955                         vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES_KHR,
956                         DE_NULL,
957                         { 0u, 0u, 0u}
958                 };
959                 m_vkiA.getPhysicalDeviceExternalBufferPropertiesKHR(m_physicalDeviceA, &info, &properties);
960
961                 log << TestLog::Message << "External buffer properties: " << info << "\n" << properties << TestLog::EndMessage;
962
963                 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR) == 0
964                                 || (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) == 0)
965                         TCU_THROW(NotSupportedError, "Exporting and importing memory type not supported");
966
967                 if (!m_config.dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR) != 0)
968                 {
969                         TCU_THROW(NotSupportedError, "Handle requires dedicated allocation, but test uses suballocated memory");
970                 }
971         }
972
973         // Check semaphore support
974         {
975                 const vk::VkPhysicalDeviceExternalSemaphoreInfoKHR      info            =
976                 {
977                         vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR,
978                         DE_NULL,
979                         m_semaphoreHandleType
980                 };
981                 vk::VkExternalSemaphorePropertiesKHR                            properties;
982
983                 m_vkiA.getPhysicalDeviceExternalSemaphorePropertiesKHR(m_physicalDeviceA, &info, &properties);
984
985                 log << TestLog::Message << info << "\n" << properties << TestLog::EndMessage;
986
987                 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR) == 0
988                                 || (properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR) == 0)
989                         TCU_THROW(NotSupportedError, "Exporting and importing semaphore type not supported");
990         }
991 }
992
993 tcu::TestStatus SharingTestInstance::iterate (void)
994 {
995         TestLog&                                                                log                                     (m_context.getTestContext().getLog());
996
997         const deUint32                                                  queueFamilyA            = (deUint32)m_queueANdx;
998         const deUint32                                                  queueFamilyB            = (deUint32)m_queueBNdx;
999
1000         const tcu::ScopedLogSection                             queuePairSection        (log,
1001                                                                                                                                         "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB),
1002                                                                                                                                         "WriteQueue-" + de::toString(queueFamilyA) + "-ReadQueue-" + de::toString(queueFamilyB));
1003
1004         const vk::Unique<vk::VkSemaphore>               semaphoreA                      (createExportableSemaphore(m_vkdA, *m_deviceA, m_semaphoreHandleType));
1005         const vk::Unique<vk::VkSemaphore>               semaphoreB                      (createSemaphore(m_vkdB, *m_deviceB));
1006
1007         deUint32                                                                exportedMemoryTypeIndex = ~0U;
1008         const de::UniquePtr<Resource>                   resourceA                       (createResource(m_vkdA, *m_deviceA, m_config.resource, m_queueFamilyIndicesA, *m_supportReadOp, *m_supportWriteOp, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated, m_getMemReq2Supported));
1009
1010         NativeHandle                                                    nativeMemoryHandle;
1011         getMemoryNative(m_vkdA, *m_deviceA, resourceA->getMemory(), m_memoryHandleType, nativeMemoryHandle);
1012
1013         const de::UniquePtr<Resource>                   resourceB                       (importResource(m_vkdB, *m_deviceB, m_config.resource, m_queueFamilyIndicesB, *m_supportReadOp, *m_supportWriteOp, nativeMemoryHandle, m_memoryHandleType, exportedMemoryTypeIndex, m_config.dedicated));
1014
1015         try
1016         {
1017                 const vk::VkQueue                                               queueA                          (getQueue(m_vkdA, *m_deviceA, queueFamilyA));
1018                 const vk::Unique<vk::VkCommandPool>             commandPoolA            (createCommandPool(m_vkdA, *m_deviceA, queueFamilyA));
1019                 const vk::Unique<vk::VkCommandBuffer>   commandBufferA          (createCommandBuffer(m_vkdA, *m_deviceA, *commandPoolA));
1020                 vk::SimpleAllocator                                             allocatorA                      (m_vkdA, *m_deviceA, vk::getPhysicalDeviceMemoryProperties(m_vkiA, m_physicalDeviceA));
1021                 const std::vector<std::string>                  deviceExtensionsA;
1022                 OperationContext                                                operationContextA       (m_vkiA, m_vkdA, m_physicalDeviceA, *m_deviceA, allocatorA, deviceExtensionsA, m_context.getBinaryCollection(), m_pipelineCacheData);
1023
1024                 if (!checkQueueFlags(m_queueFamiliesA[m_queueANdx].queueFlags , m_supportWriteOp->getQueueFlags(operationContextA)))
1025                         TCU_THROW(NotSupportedError, "Operation not supported by the source queue");
1026
1027                 const vk::VkQueue                                               queueB                          (getQueue(m_vkdB, *m_deviceB, queueFamilyB));
1028                 const vk::Unique<vk::VkCommandPool>             commandPoolB            (createCommandPool(m_vkdB, *m_deviceB, queueFamilyB));
1029                 const vk::Unique<vk::VkCommandBuffer>   commandBufferB          (createCommandBuffer(m_vkdB, *m_deviceB, *commandPoolB));
1030                 vk::SimpleAllocator                                             allocatorB                      (m_vkdB, *m_deviceB, vk::getPhysicalDeviceMemoryProperties(m_vkiB, m_physicalDeviceB));
1031                 const std::vector<std::string>                  deviceExtensionsB;
1032                 OperationContext                                                operationContextB       (m_vkiB, m_vkdB, m_physicalDeviceB, *m_deviceB, allocatorB, deviceExtensionsB, m_context.getBinaryCollection(), m_pipelineCacheData);
1033
1034                 if (!checkQueueFlags(m_queueFamiliesB[m_queueBNdx].queueFlags , m_supportReadOp->getQueueFlags(operationContextB)))
1035                         TCU_THROW(NotSupportedError, "Operation not supported by the destination queue");
1036
1037                 const de::UniquePtr<Operation>                  writeOp                         (m_supportWriteOp->build(operationContextA, *resourceA));
1038                 const de::UniquePtr<Operation>                  readOp                          (m_supportReadOp->build(operationContextB, *resourceB));
1039
1040                 const SyncInfo                                                  writeSync                       = writeOp->getSyncInfo();
1041                 const SyncInfo                                                  readSync                        = readOp->getSyncInfo();
1042
1043                 beginCommandBuffer(m_vkdA, *commandBufferA);
1044                 writeOp->recordCommands(*commandBufferA);
1045                 recordWriteBarrier(m_vkdA, *commandBufferA, *resourceA, writeSync, queueFamilyA, readSync);
1046                 endCommandBuffer(m_vkdA, *commandBufferA);
1047
1048                 beginCommandBuffer(m_vkdB, *commandBufferB);
1049                 recordReadBarrier(m_vkdB, *commandBufferB, *resourceB, writeSync, readSync, queueFamilyB);
1050                 readOp->recordCommands(*commandBufferB);
1051                 endCommandBuffer(m_vkdB, *commandBufferB);
1052
1053                 {
1054                         const vk::VkCommandBuffer       commandBuffer   = *commandBufferA;
1055                         const vk::VkSemaphore           semaphore               = *semaphoreA;
1056                         const vk::VkSubmitInfo          submitInfo              =
1057                         {
1058                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1059                                 DE_NULL,
1060
1061                                 0u,
1062                                 DE_NULL,
1063                                 DE_NULL,
1064
1065                                 1u,
1066                                 &commandBuffer,
1067                                 1u,
1068                                 &semaphore
1069                         };
1070
1071                         VK_CHECK(m_vkdA.queueSubmit(queueA, 1u, &submitInfo, DE_NULL));
1072
1073                         {
1074                                 NativeHandle    nativeSemaphoreHandle;
1075
1076                                 getSemaphoreNative(m_vkdA, *m_deviceA, *semaphoreA, m_semaphoreHandleType, nativeSemaphoreHandle);
1077                                 importSemaphore(m_vkdB, *m_deviceB, *semaphoreB, m_semaphoreHandleType, nativeSemaphoreHandle, 0u);
1078                         }
1079                 }
1080                 {
1081                         const vk::VkCommandBuffer               commandBuffer   = *commandBufferB;
1082                         const vk::VkSemaphore                   semaphore               = *semaphoreB;
1083                         const vk::VkPipelineStageFlags  dstStage                = readSync.stageMask;
1084                         const vk::VkSubmitInfo                  submitInfo              =
1085                         {
1086                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
1087                                 DE_NULL,
1088
1089                                 1u,
1090                                 &semaphore,
1091                                 &dstStage,
1092
1093                                 1u,
1094                                 &commandBuffer,
1095                                 0u,
1096                                 DE_NULL,
1097                         };
1098
1099                         VK_CHECK(m_vkdB.queueSubmit(queueB, 1u, &submitInfo, DE_NULL));
1100                 }
1101
1102                 VK_CHECK(m_vkdA.queueWaitIdle(queueA));
1103                 VK_CHECK(m_vkdB.queueWaitIdle(queueB));
1104
1105                 {
1106                         const Data      expected        = writeOp->getData();
1107                         const Data      actual          = readOp->getData();
1108
1109                         DE_ASSERT(expected.size == actual.size);
1110
1111                         if (0 != deMemCmp(expected.data, actual.data, expected.size))
1112                         {
1113                                 const size_t            maxBytesLogged  = 256;
1114                                 std::ostringstream      expectedData;
1115                                 std::ostringstream      actualData;
1116                                 size_t                          byteNdx                 = 0;
1117
1118                                 // Find first byte difference
1119                                 for (; actual.data[byteNdx] == expected.data[byteNdx]; byteNdx++)
1120                                 {
1121                                         // Nothing
1122                                 }
1123
1124                                 log << TestLog::Message << "First different byte at offset: " << byteNdx << TestLog::EndMessage;
1125
1126                                 // Log 8 previous bytes before the first incorrect byte
1127                                 if (byteNdx > 8)
1128                                 {
1129                                         expectedData << "... ";
1130                                         actualData << "... ";
1131
1132                                         byteNdx -= 8;
1133                                 }
1134                                 else
1135                                         byteNdx = 0;
1136
1137                                 for (size_t i = 0; i < maxBytesLogged && byteNdx < expected.size; i++, byteNdx++)
1138                                 {
1139                                         expectedData << (i > 0 ? ", " : "") << (deUint32)expected.data[byteNdx];
1140                                         actualData << (i > 0 ? ", " : "") << (deUint32)actual.data[byteNdx];
1141                                 }
1142
1143                                 if (expected.size > byteNdx)
1144                                 {
1145                                         expectedData << "...";
1146                                         actualData << "...";
1147                                 }
1148
1149                                 log << TestLog::Message << "Expected data: (" << expectedData.str() << ")" << TestLog::EndMessage;
1150                                 log << TestLog::Message << "Actual data: (" << actualData.str() << ")" << TestLog::EndMessage;
1151
1152                                 m_resultCollector.fail("Memory contents don't match");
1153                         }
1154                 }
1155         }
1156         catch (const tcu::NotSupportedError& error)
1157         {
1158                 log << TestLog::Message << "Not supported: " << error.getMessage() << TestLog::EndMessage;
1159         }
1160         catch (const tcu::TestError& error)
1161         {
1162                 m_resultCollector.fail(std::string("Exception: ") + error.getMessage());
1163         }
1164
1165         // Move to next queue
1166         {
1167                 m_queueBNdx++;
1168
1169                 if (m_queueBNdx >= m_queueFamiliesB.size())
1170                 {
1171                         m_queueANdx++;
1172
1173                         if (m_queueANdx >= m_queueFamiliesA.size())
1174                         {
1175                                 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1176                         }
1177                         else
1178                         {
1179                                 m_queueBNdx = 0;
1180
1181                                 return tcu::TestStatus::incomplete();
1182                         }
1183                 }
1184                 else
1185                         return tcu::TestStatus::incomplete();
1186         }
1187 }
1188
1189 struct Progs
1190 {
1191         void init (vk::SourceCollections& dst, TestConfig config) const
1192         {
1193                 const de::UniquePtr<OperationSupport>   readOp  (makeOperationSupport(config.readOp, config.resource));
1194                 const de::UniquePtr<OperationSupport>   writeOp (makeOperationSupport(config.writeOp, config.resource));
1195
1196                 readOp->initPrograms(dst);
1197                 writeOp->initPrograms(dst);
1198         }
1199 };
1200
1201 } // anonymous
1202
1203 tcu::TestCaseGroup* createCrossInstanceSharingTest (tcu::TestContext& testCtx)
1204 {
1205         const struct
1206         {
1207                 vk::VkExternalMemoryHandleTypeFlagBitsKHR               memoryType;
1208                 vk::VkExternalSemaphoreHandleTypeFlagBitsKHR    semaphoreType;
1209                 const char*                                                                             nameSuffix;
1210         } cases[] =
1211         {
1212                 {
1213                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1214                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1215                         "_fd"
1216                 },
1217                 {
1218                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
1219                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR,
1220                         "_fence_fd"
1221                 },
1222                 {
1223                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1224                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHR,
1225                         "_win32_kmt"
1226                 },
1227                 {
1228                         vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1229                         vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHR,
1230                         "_win32"
1231                 },
1232         };
1233         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "cross_instance", ""));
1234
1235         for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
1236         {
1237                 const bool                                              dedicated               (dedicatedNdx == 1);
1238                 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup  (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
1239
1240                 for (size_t writeOpNdx = 0; writeOpNdx < DE_LENGTH_OF_ARRAY(s_writeOps); ++writeOpNdx)
1241                 for (size_t readOpNdx = 0; readOpNdx < DE_LENGTH_OF_ARRAY(s_readOps); ++readOpNdx)
1242                 {
1243                         const OperationName     writeOp         = s_writeOps[writeOpNdx];
1244                         const OperationName     readOp          = s_readOps[readOpNdx];
1245                         const std::string       opGroupName     = getOperationName(writeOp) + "_" + getOperationName(readOp);
1246                         bool                            empty           = true;
1247
1248                         de::MovePtr<tcu::TestCaseGroup> opGroup (new tcu::TestCaseGroup(testCtx, opGroupName.c_str(), ""));
1249
1250                         for (size_t resourceNdx = 0; resourceNdx < DE_LENGTH_OF_ARRAY(s_resources); ++resourceNdx)
1251                         {
1252                                 const ResourceDescription&      resource        = s_resources[resourceNdx];
1253
1254                                 for (size_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1255                                 {
1256                                         std::string     name= getResourceName(resource) + cases[caseNdx].nameSuffix;
1257
1258                                         if (isResourceSupported(writeOp, resource) && isResourceSupported(readOp, resource))
1259                                         {
1260                                                 const TestConfig config (resource, writeOp, readOp, cases[caseNdx].memoryType, cases[caseNdx].semaphoreType, dedicated);
1261
1262                                                 opGroup->addChild(new InstanceFactory1<SharingTestInstance, TestConfig, Progs>(testCtx, tcu::NODETYPE_SELF_VALIDATE,  name, "", Progs(), config));
1263                                                 empty = false;
1264                                         }
1265                                 }
1266                         }
1267
1268                         if (!empty)
1269                                 dedicatedGroup->addChild(opGroup.release());
1270                 }
1271
1272                 group->addChild(dedicatedGroup.release());
1273         }
1274
1275         return group.release();
1276 }
1277
1278 } // synchronization
1279 } // vkt