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