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