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