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