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