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