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