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