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