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