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