1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google 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  * \brief Vulkan external memory API tests
20  *//*--------------------------------------------------------------------*/
21 
22 #include "vktApiExternalMemoryTests.hpp"
23 
24 #include "vktTestCaseUtil.hpp"
25 #include "vkRefUtil.hpp"
26 #include "vkDeviceUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkPlatform.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkApiVersion.hpp"
31 
32 #include "tcuTestLog.hpp"
33 
34 #include "deUniquePtr.hpp"
35 #include "deStringUtil.hpp"
36 #include "deRandom.hpp"
37 
38 #include "deMemory.h"
39 
40 #include "vktExternalMemoryUtil.hpp"
41 
42 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
43 #	include <unistd.h>
44 #	include <fcntl.h>
45 #	include <errno.h>
46 #	include <sys/types.h>
47 #	include <sys/socket.h>
48 #endif
49 
50 #if (DE_OS == DE_OS_WIN32)
51 #	define WIN32_LEAN_AND_MEAN
52 #	include <windows.h>
53 #	include <Dxgi1_2.h>
54 #endif
55 
56 using tcu::TestLog;
57 using namespace vkt::ExternalMemoryUtil;
58 
59 namespace vkt
60 {
61 namespace api
62 {
63 namespace
64 {
65 
66 
getFormatCaseName(vk::VkFormat format)67 std::string getFormatCaseName (vk::VkFormat format)
68 {
69 	return de::toLower(de::toString(getFormatStr(format)).substr(10));
70 }
71 
getMemoryDedicatedRequirements(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer)72 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface&	vkd,
73 																  vk::VkDevice					device,
74 																  vk::VkBuffer					buffer)
75 {
76 	const vk::VkBufferMemoryRequirementsInfo2	requirementInfo			=
77 	{
78 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
79 		DE_NULL,
80 		buffer
81 	};
82 	vk::VkMemoryDedicatedRequirements			dedicatedRequirements	=
83 	{
84 		vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
85 		DE_NULL,
86 		VK_FALSE,
87 		VK_FALSE
88 	};
89 	vk::VkMemoryRequirements2					requirements			=
90 	{
91 		vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
92 		&dedicatedRequirements,
93 		{ 0u, 0u, 0u }
94 	};
95 
96 	vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
97 
98 	return dedicatedRequirements;
99 }
100 
getMemoryDedicatedRequirements(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image)101 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface&	vkd,
102 																  vk::VkDevice					device,
103 																  vk::VkImage					image)
104 {
105 	const vk::VkImageMemoryRequirementsInfo2	requirementInfo		=
106 	{
107 		vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
108 		DE_NULL,
109 		image
110 	};
111 	vk::VkMemoryDedicatedRequirements		dedicatedRequirements	=
112 	{
113 		vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
114 		DE_NULL,
115 		VK_FALSE,
116 		VK_FALSE
117 	};
118 	vk::VkMemoryRequirements2				requirements			=
119 	{
120 		vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
121 		&dedicatedRequirements,
122 		{ 0u, 0u, 0u }
123 	};
124 
125 	vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
126 
127 	return dedicatedRequirements;
128 }
129 
writeHostMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,size_t size,const void * data)130 void writeHostMemory (const vk::DeviceInterface&	vkd,
131 					  vk::VkDevice					device,
132 					  vk::VkDeviceMemory			memory,
133 					  size_t						size,
134 					  const void*					data)
135 {
136 	void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
137 
138 	deMemcpy(ptr, data, size);
139 
140 	flushMappedMemoryRange(vkd, device, memory, 0, size);
141 
142 	vkd.unmapMemory(device, memory);
143 }
144 
checkHostMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,size_t size,const void * data)145 void checkHostMemory (const vk::DeviceInterface&	vkd,
146 					  vk::VkDevice					device,
147 					  vk::VkDeviceMemory			memory,
148 					  size_t						size,
149 					  const void*					data)
150 {
151 	void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
152 
153 	invalidateMappedMemoryRange(vkd, device, memory, 0, size);
154 
155 	if (deMemCmp(ptr, data, size) != 0)
156 		TCU_FAIL("Memory contents don't match");
157 
158 	vkd.unmapMemory(device, memory);
159 }
160 
genTestData(deUint32 seed,size_t size)161 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
162 {
163 	de::Random				rng		(seed);
164 	std::vector<deUint8>	data	(size);
165 
166 	for (size_t ndx = 0; ndx < size; ndx++)
167 	{
168 		data[ndx] = rng.getUint8();
169 	}
170 
171 	return data;
172 }
173 
chooseQueueFamilyIndex(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkQueueFlags requireFlags)174 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface&	vki,
175 								 vk::VkPhysicalDevice			device,
176 								 vk::VkQueueFlags				requireFlags)
177 {
178 	const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
179 
180 	for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
181 	{
182 		if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
183 			return queueFamilyIndex;
184 	}
185 
186 	TCU_THROW(NotSupportedError, "Queue type not supported");
187 }
188 
getInstanceExtensions(const deUint32 instanceVersion,const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)189 std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion,
190 												const vk::VkExternalSemaphoreHandleTypeFlags	externalSemaphoreTypes,
191 												const vk::VkExternalMemoryHandleTypeFlags		externalMemoryTypes,
192 												const vk::VkExternalFenceHandleTypeFlags		externalFenceTypes)
193 {
194 	std::vector<std::string> instanceExtensions;
195 
196 	if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
197 		instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
198 
199 	if (externalSemaphoreTypes != 0)
200 		if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
201 			instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
202 
203 	if (externalMemoryTypes != 0)
204 		if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
205 			instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
206 
207 	if (externalFenceTypes != 0)
208 		if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
209 			instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
210 
211 	return instanceExtensions;
212 }
213 
createInstance(const vk::PlatformInterface & vkp,const deUint32 version,const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)214 vk::Move<vk::VkInstance> createInstance (const vk::PlatformInterface&					vkp,
215 										 const deUint32									version,
216 										 const vk::VkExternalSemaphoreHandleTypeFlags	externalSemaphoreTypes,
217 										 const vk::VkExternalMemoryHandleTypeFlags		externalMemoryTypes,
218 										 const vk::VkExternalFenceHandleTypeFlags		externalFenceTypes)
219 {
220 	try
221 	{
222 		return vk::createDefaultInstance(vkp, version, std::vector<std::string>(), getInstanceExtensions(version, externalSemaphoreTypes, externalMemoryTypes, externalFenceTypes));
223 	}
224 	catch (const vk::Error& error)
225 	{
226 		if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
227 			TCU_THROW(NotSupportedError, "Required extensions not supported");
228 
229 		throw;
230 	}
231 }
232 
createDevice(const deUint32 apiVersion,const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,deUint32 queueFamilyIndex,bool useDedicatedAllocs=false)233 vk::Move<vk::VkDevice> createDevice (const deUint32									apiVersion,
234 									 const vk::PlatformInterface&					vkp,
235 									 vk::VkInstance									instance,
236 									 const vk::InstanceInterface&					vki,
237 									 vk::VkPhysicalDevice							physicalDevice,
238 									 const vk::VkExternalSemaphoreHandleTypeFlags	externalSemaphoreTypes,
239 									 const vk::VkExternalMemoryHandleTypeFlags		externalMemoryTypes,
240 									 const vk::VkExternalFenceHandleTypeFlags		externalFenceTypes,
241 									 deUint32										queueFamilyIndex,
242 									 bool											useDedicatedAllocs = false)
243 {
244 	std::vector<const char*>	deviceExtensions;
245 
246 	if ((externalSemaphoreTypes
247 			& (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
248 				| vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
249 	{
250 		deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
251 	}
252 
253 	if ((externalFenceTypes
254 			& (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
255 				| vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
256 	{
257 		deviceExtensions.push_back("VK_KHR_external_fence_fd");
258 	}
259 
260 	if (useDedicatedAllocs)
261 	{
262 		if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
263 			deviceExtensions.push_back("VK_KHR_dedicated_allocation");
264 		if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
265 			deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
266 	}
267 
268 	if ((externalMemoryTypes
269 			& vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) != 0)
270 	{
271 		deviceExtensions.push_back("VK_KHR_external_memory_fd");
272 	}
273 
274 	if ((externalSemaphoreTypes
275 			& (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
276 				| vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
277 	{
278 		deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
279 	}
280 
281 	if ((externalFenceTypes
282 			& (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
283 				| vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
284 	{
285 		deviceExtensions.push_back("VK_KHR_external_fence_win32");
286 	}
287 
288 	if ((externalMemoryTypes
289 			& (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
290 			   | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
291 			   | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
292 			   | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
293 			   | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
294 			   | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
295 	{
296 		deviceExtensions.push_back("VK_KHR_external_memory_win32");
297 	}
298 
299 	if ((externalMemoryTypes
300 		& vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
301 	{
302 		deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
303 	}
304 
305 	const float								priority				= 0.5f;
306 	const vk::VkDeviceQueueCreateInfo		queues[]				=
307 	{
308 		{
309 			vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
310 			DE_NULL,
311 			0u,
312 
313 			queueFamilyIndex,
314 			1u,
315 			&priority
316 		}
317 	};
318 	const vk::VkDeviceCreateInfo			deviceCreateInfo		=
319 	{
320 		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
321 		DE_NULL,
322 		0u,
323 
324 		DE_LENGTH_OF_ARRAY(queues),
325 		queues,
326 
327 		0u,
328 		DE_NULL,
329 
330 		(deUint32)deviceExtensions.size(),
331 		deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
332 		DE_NULL
333 	};
334 
335 	try
336 	{
337 		return vk::createDevice(vkp, instance, vki, physicalDevice, &deviceCreateInfo);
338 	}
339 	catch (const vk::Error& error)
340 	{
341 		if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
342 			TCU_THROW(NotSupportedError, "Required extensions not supported");
343 
344 		throw;
345 	}
346 }
347 
getQueue(const vk::DeviceInterface & vkd,vk::VkDevice device,deUint32 queueFamilyIndex)348 vk::VkQueue getQueue (const vk::DeviceInterface&	vkd,
349 					  vk::VkDevice					device,
350 					  deUint32						queueFamilyIndex)
351 {
352 	vk::VkQueue queue;
353 
354 	vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
355 
356 	return queue;
357 }
358 
checkSemaphoreSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)359 void checkSemaphoreSupport (const vk::InstanceInterface&				vki,
360 							vk::VkPhysicalDevice						device,
361 							vk::VkExternalSemaphoreHandleTypeFlagBits	externalType)
362 {
363 	const vk::VkPhysicalDeviceExternalSemaphoreInfo	info		=
364 	{
365 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
366 		DE_NULL,
367 		externalType
368 	};
369 	vk::VkExternalSemaphoreProperties				properties	=
370 	{
371 		vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
372 		DE_NULL,
373 		0u,
374 		0u,
375 		0u
376 	};
377 
378 	vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
379 
380 	if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
381 		TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
382 
383 	if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
384 		TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
385 }
386 
checkFenceSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalFenceHandleTypeFlagBits externalType)387 void checkFenceSupport (const vk::InstanceInterface&			vki,
388 						vk::VkPhysicalDevice					device,
389 						vk::VkExternalFenceHandleTypeFlagBits	externalType)
390 {
391 	const vk::VkPhysicalDeviceExternalFenceInfo	info		=
392 	{
393 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
394 		DE_NULL,
395 		externalType
396 	};
397 	vk::VkExternalFenceProperties				properties	=
398 	{
399 		vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
400 		DE_NULL,
401 		0u,
402 		0u,
403 		0u
404 	};
405 
406 	vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
407 
408 	if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
409 		TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
410 
411 	if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
412 		TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
413 }
414 
checkBufferSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkBufferViewCreateFlags createFlag,vk::VkBufferUsageFlags usageFlag,bool dedicated)415 void checkBufferSupport (const vk::InstanceInterface&				vki,
416 						 vk::VkPhysicalDevice						device,
417 						 vk::VkExternalMemoryHandleTypeFlagBits		externalType,
418 						 vk::VkBufferViewCreateFlags				createFlag,
419 						 vk::VkBufferUsageFlags						usageFlag,
420 						 bool										dedicated)
421 {
422 	const vk::VkPhysicalDeviceExternalBufferInfo	info		=
423 	{
424 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
425 		DE_NULL,
426 
427 		createFlag,
428 		usageFlag,
429 		externalType
430 	};
431 	vk::VkExternalBufferProperties					properties	=
432 	{
433 		vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
434 		DE_NULL,
435 
436 		{ 0u, 0u, 0u }
437 	};
438 
439 	vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
440 
441 	if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
442 		TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
443 
444 	if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
445 		TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
446 
447 	if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
448 		TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
449 }
450 
checkImageSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkImageViewCreateFlags createFlag,vk::VkImageUsageFlags usageFlag,vk::VkFormat format,vk::VkImageTiling tiling,bool dedicated)451 void checkImageSupport (const vk::InstanceInterface&						vki,
452 						 vk::VkPhysicalDevice								device,
453 						 vk::VkExternalMemoryHandleTypeFlagBits				externalType,
454 						 vk::VkImageViewCreateFlags							createFlag,
455 						 vk::VkImageUsageFlags								usageFlag,
456 						 vk::VkFormat										format,
457 						 vk::VkImageTiling									tiling,
458 						 bool												dedicated)
459 {
460 	const vk::VkPhysicalDeviceExternalImageFormatInfo	externalInfo		=
461 	{
462 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
463 		DE_NULL,
464 		externalType
465 	};
466 	const vk::VkPhysicalDeviceImageFormatInfo2			info				=
467 	{
468 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
469 		&externalInfo,
470 
471 		format,
472 		vk::VK_IMAGE_TYPE_2D,
473 		tiling,
474 		usageFlag,
475 		createFlag,
476 	};
477 	vk::VkExternalImageFormatProperties					externalProperties	=
478 	{
479 		vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
480 		DE_NULL,
481 		{ 0u, 0u, 0u }
482 	};
483 	vk::VkImageFormatProperties2						properties			=
484 	{
485 		vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
486 		&externalProperties,
487 		{
488 			{ 0u, 0u, 0u },
489 			0u,
490 			0u,
491 			0u,
492 			0u
493 		}
494 	};
495 
496 	vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
497 
498 	if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
499 		TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
500 
501 	if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
502 		TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
503 
504 	if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
505 		TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
506 }
507 
submitDummySignal(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkSemaphore semaphore)508 void submitDummySignal (const vk::DeviceInterface&	vkd,
509 						vk::VkQueue					queue,
510 						vk::VkSemaphore				semaphore)
511 {
512 	const vk::VkSubmitInfo submit =
513 	{
514 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
515 		DE_NULL,
516 
517 		0u,
518 		DE_NULL,
519 		DE_NULL,
520 
521 		0u,
522 		DE_NULL,
523 
524 		1u,
525 		&semaphore
526 	};
527 
528 	VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
529 }
530 
submitDummySignalAndGetSemaphoreNative(const vk::DeviceInterface & vk,vk::VkDevice device,vk::VkQueue queue,deUint32 queueFamilyIndex,vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & nativeHandle)531 void submitDummySignalAndGetSemaphoreNative (	const vk::DeviceInterface&						vk,
532 												vk::VkDevice									device,
533 												vk::VkQueue										queue,
534 												deUint32										queueFamilyIndex,
535 												vk::VkSemaphore									semaphore,
536 												vk::VkExternalSemaphoreHandleTypeFlagBits		externalType,
537 												NativeHandle&									nativeHandle)
538 {
539 	const vk::Unique<vk::VkCommandPool>		cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
540 	const vk::Unique<vk::VkCommandBuffer>	cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
541 
542 	const vk::VkEventCreateInfo eventCreateInfo =
543 	{
544 		vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
545 		DE_NULL,
546 		0u
547 	};
548 
549 	const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
550 
551 	const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
552 	{
553 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
554 		DE_NULL,
555 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
556 		DE_NULL,
557 	};
558 
559 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
560 	/*
561 		The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
562 		VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
563 		may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the
564 		handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence
565 		is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned
566 		we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
567 	*/
568 	vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
569 	vk.endCommandBuffer(*cmdBuffer);
570 
571 	const vk::VkSubmitInfo submit =
572 	{
573 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
574 		DE_NULL,
575 
576 		0u,
577 		DE_NULL,
578 		DE_NULL,
579 
580 		1u,
581 		&cmdBuffer.get(),
582 
583 		1u,
584 		&semaphore
585 	};
586 
587 	VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
588 
589 	getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
590 
591 	VK_CHECK(vk.setEvent(device, *event));
592 
593 	VK_CHECK(vk.queueWaitIdle(queue));
594 }
595 
submitDummyWait(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkSemaphore semaphore)596 void submitDummyWait (const vk::DeviceInterface&	vkd,
597 					  vk::VkQueue					queue,
598 					  vk::VkSemaphore				semaphore)
599 {
600 	const vk::VkPipelineStageFlags	stage	= vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
601 	const vk::VkSubmitInfo			submit	=
602 	{
603 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
604 		DE_NULL,
605 
606 		1u,
607 		&semaphore,
608 		&stage,
609 
610 		0u,
611 		DE_NULL,
612 
613 		0u,
614 		DE_NULL,
615 	};
616 
617 	VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
618 }
619 
submitDummySignal(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkFence fence)620 void submitDummySignal (const vk::DeviceInterface&	vkd,
621 						vk::VkQueue					queue,
622 						vk::VkFence					fence)
623 {
624 	const vk::VkSubmitInfo submit =
625 	{
626 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
627 		DE_NULL,
628 
629 		0u,
630 		DE_NULL,
631 		DE_NULL,
632 
633 		0u,
634 		DE_NULL,
635 
636 		0u,
637 		DE_NULL
638 	};
639 
640 	VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
641 }
642 
submitDummySignalAndGetFenceNative(const vk::DeviceInterface & vk,vk::VkDevice device,vk::VkQueue queue,deUint32 queueFamilyIndex,vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & nativeHandle)643 void submitDummySignalAndGetFenceNative (	const vk::DeviceInterface&					vk,
644 											vk::VkDevice								device,
645 											vk::VkQueue									queue,
646 											deUint32									queueFamilyIndex,
647 											vk::VkFence									fence,
648 											vk::VkExternalFenceHandleTypeFlagBits		externalType,
649 											NativeHandle&								nativeHandle)
650 {
651 	const vk::Unique<vk::VkCommandPool>		cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
652 	const vk::Unique<vk::VkCommandBuffer>	cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
653 
654 	const vk::VkEventCreateInfo eventCreateInfo =
655 	{
656 		vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
657 		DE_NULL,
658 		0u
659 	};
660 
661 	const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
662 
663 	const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
664 	{
665 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
666 		DE_NULL,
667 		vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
668 		DE_NULL,
669 	};
670 
671 	VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
672 	/*
673 		The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
674 		VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
675 		could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the
676 		handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a
677 		file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned
678 		we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
679 	*/
680 	vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
681 	vk.endCommandBuffer(*cmdBuffer);
682 
683 	const vk::VkSubmitInfo submit =
684 	{
685 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
686 		DE_NULL,
687 
688 		0u,
689 		DE_NULL,
690 		DE_NULL,
691 
692 		1u,
693 		&cmdBuffer.get(),
694 
695 		0u,
696 		DE_NULL
697 	};
698 
699 	VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
700 
701 	getFenceNative(vk, device, fence, externalType, nativeHandle);
702 
703 	VK_CHECK(vk.setEvent(device, *event));
704 
705 	VK_CHECK(vk.queueWaitIdle(queue));
706 }
707 
testSemaphoreQueries(Context & context,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)708 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
709 {
710 	const vk::PlatformInterface&		vkp				(context.getPlatformInterface());
711 	const vk::Unique<vk::VkInstance>	instance		(createInstance(vkp, context.getUsedApiVersion(), externalType, 0u, 0u));
712 	const vk::InstanceDriver			vki				(vkp, *instance);
713 	const vk::VkPhysicalDevice			device			(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
714 
715 	TestLog&							log				= context.getTestContext().getLog();
716 
717 	const vk::VkPhysicalDeviceExternalSemaphoreInfo	info		=
718 	{
719 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
720 		DE_NULL,
721 		externalType
722 	};
723 	vk::VkExternalSemaphoreProperties				properties	=
724 	{
725 		vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
726 		DE_NULL,
727 		0u,
728 		0u,
729 		0u
730 	};
731 
732 	vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
733 	log << TestLog::Message << properties << TestLog::EndMessage;
734 
735 	TCU_CHECK(properties.pNext == DE_NULL);
736 	TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
737 
738 	return tcu::TestStatus::pass("Pass");
739 }
740 
741 struct SemaphoreTestConfig
742 {
SemaphoreTestConfigvkt::api::__anon041f48660111::SemaphoreTestConfig743 													SemaphoreTestConfig	(vk::VkExternalSemaphoreHandleTypeFlagBits	externalType_,
744 																		 Permanence										permanence_)
745 		: externalType		(externalType_)
746 		, permanence		(permanence_)
747 	{
748 	}
749 
750 	vk::VkExternalSemaphoreHandleTypeFlagBits	externalType;
751 	Permanence									permanence;
752 };
753 
testSemaphoreWin32Create(Context & context,const SemaphoreTestConfig config)754 tcu::TestStatus testSemaphoreWin32Create (Context&					context,
755 										  const SemaphoreTestConfig	config)
756 {
757 #if (DE_OS == DE_OS_WIN32)
758 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
759 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
760 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
761 	const vk::InstanceDriver			vki					(vkp, *instance);
762 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
763 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
764 
765 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
766 
767 	{
768 		const vk::Unique<vk::VkDevice>					device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
769 		const vk::DeviceDriver							vkd				(vkp, *instance, *device);
770 		const vk::VkQueue								queue			(getQueue(vkd, *device, queueFamilyIndex));
771 		const vk::VkExportSemaphoreWin32HandleInfoKHR	win32ExportInfo	=
772 		{
773 			vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
774 			DE_NULL,
775 
776 			(vk::pt::Win32SecurityAttributesPtr)DE_NULL,
777 			DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
778 			DE_NULL
779 		};
780 		const vk::VkExportSemaphoreCreateInfo			exportCreateInfo=
781 		{
782 			vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
783 			&win32ExportInfo,
784 			(vk::VkExternalMemoryHandleTypeFlags)config.externalType
785 		};
786 		const vk::VkSemaphoreCreateInfo					createInfo		=
787 		{
788 			vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
789 			&exportCreateInfo,
790 			0u
791 		};
792 		const vk::Unique<vk::VkSemaphore>				semaphore		(vk::createSemaphore(vkd, *device, &createInfo));
793 
794 		if (transference == TRANSFERENCE_COPY)
795 			submitDummySignal(vkd, queue, *semaphore);
796 
797 		NativeHandle									handleA;
798 		getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
799 
800 		{
801 			const vk::VkSemaphoreImportFlags			flags			= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
802 			const vk::Unique<vk::VkSemaphore>			semaphoreA		(createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
803 
804 			if (transference == TRANSFERENCE_COPY)
805 				submitDummyWait(vkd, queue, *semaphoreA);
806 			else if (transference == TRANSFERENCE_REFERENCE)
807 			{
808 				submitDummySignal(vkd, queue, *semaphore);
809 				submitDummyWait(vkd, queue, *semaphoreA);
810 			}
811 			else
812 				DE_FATAL("Unknown transference.");
813 
814 			VK_CHECK(vkd.queueWaitIdle(queue));
815 		}
816 
817 		return tcu::TestStatus::pass("Pass");
818 	}
819 #else
820 	DE_UNREF(context);
821 	DE_UNREF(config);
822 	TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
823 #endif
824 }
825 
testSemaphoreImportTwice(Context & context,const SemaphoreTestConfig config)826 tcu::TestStatus testSemaphoreImportTwice (Context&					context,
827 										  const SemaphoreTestConfig	config)
828 {
829 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
830 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
831 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
832 	const vk::InstanceDriver			vki					(vkp, *instance);
833 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
834 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
835 
836 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
837 
838 	{
839 		const vk::Unique<vk::VkDevice>		device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
840 		const vk::DeviceDriver				vkd				(vkp, *instance, *device);
841 		const vk::VkQueue					queue			(getQueue(vkd, *device, queueFamilyIndex));
842 		const vk::Unique<vk::VkSemaphore>	semaphore		(createExportableSemaphore(vkd, *device, config.externalType));
843 		NativeHandle						handleA;
844 
845 		if (transference == TRANSFERENCE_COPY)
846 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
847 		else
848 			getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
849 
850 		{
851 			NativeHandle						handleB		(handleA);
852 			const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
853 			const vk::Unique<vk::VkSemaphore>	semaphoreA	(createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
854 			const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
855 
856 			if (transference == TRANSFERENCE_COPY)
857 				submitDummyWait(vkd, queue, *semaphoreA);
858 			else if (transference == TRANSFERENCE_REFERENCE)
859 			{
860 				submitDummySignal(vkd, queue, *semaphoreA);
861 				submitDummyWait(vkd, queue, *semaphoreB);
862 			}
863 			else
864 				DE_FATAL("Unknown transference.");
865 
866 			VK_CHECK(vkd.queueWaitIdle(queue));
867 		}
868 
869 		return tcu::TestStatus::pass("Pass");
870 	}
871 }
872 
testSemaphoreImportReimport(Context & context,const SemaphoreTestConfig config)873 tcu::TestStatus testSemaphoreImportReimport (Context&					context,
874 											 const SemaphoreTestConfig	config)
875 {
876 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
877 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
878 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
879 	const vk::InstanceDriver			vki					(vkp, *instance);
880 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
881 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
882 
883 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
884 
885 	{
886 		const vk::Unique<vk::VkDevice>		device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
887 		const vk::DeviceDriver				vkd				(vkp, *instance, *device);
888 		const vk::VkQueue					queue			(getQueue(vkd, *device, queueFamilyIndex));
889 
890 		const vk::Unique<vk::VkSemaphore>	semaphoreA		(createExportableSemaphore(vkd, *device, config.externalType));
891 		NativeHandle						handleA;
892 
893 		if (transference == TRANSFERENCE_COPY)
894 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
895 		else
896 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
897 
898 		NativeHandle						handleB		(handleA);
899 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
900 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
901 
902 		importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
903 
904 		if (transference == TRANSFERENCE_COPY)
905 			submitDummyWait(vkd, queue, *semaphoreB);
906 		else if (transference == TRANSFERENCE_REFERENCE)
907 		{
908 			submitDummySignal(vkd, queue, *semaphoreA);
909 			submitDummyWait(vkd, queue, *semaphoreB);
910 		}
911 		else
912 			DE_FATAL("Unknown transference.");
913 
914 		VK_CHECK(vkd.queueWaitIdle(queue));
915 
916 		return tcu::TestStatus::pass("Pass");
917 	}
918 }
919 
testSemaphoreSignalExportImportWait(Context & context,const SemaphoreTestConfig config)920 tcu::TestStatus testSemaphoreSignalExportImportWait (Context&					context,
921 													 const SemaphoreTestConfig	config)
922 {
923 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
924 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
925 	const vk::InstanceDriver			vki					(vkp, *instance);
926 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
927 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
928 
929 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
930 
931 	{
932 		const vk::Unique<vk::VkDevice>		device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
933 		const vk::DeviceDriver				vkd					(vkp, *instance, *device);
934 		const vk::VkQueue					queue				(getQueue(vkd, *device, queueFamilyIndex));
935 		const vk::Unique<vk::VkSemaphore>	semaphoreA			(createExportableSemaphore(vkd, *device, config.externalType));
936 		{
937 			NativeHandle	handle;
938 
939 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
940 
941 			{
942 				const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
943 				const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
944 				submitDummyWait(vkd, queue, *semaphoreB);
945 
946 				VK_CHECK(vkd.queueWaitIdle(queue));
947 			}
948 		}
949 
950 		return tcu::TestStatus::pass("Pass");
951 	}
952 }
953 
testSemaphoreExportSignalImportWait(Context & context,const SemaphoreTestConfig config)954 tcu::TestStatus testSemaphoreExportSignalImportWait (Context&					context,
955 													 const SemaphoreTestConfig	config)
956 {
957 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
958 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
959 	const vk::InstanceDriver			vki					(vkp, *instance);
960 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
961 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
962 	const vk::VkSemaphoreImportFlags	flags				= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
963 
964 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
965 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
966 
967 	{
968 		const vk::Unique<vk::VkDevice>		device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
969 		const vk::DeviceDriver				vkd					(vkp, *instance, *device);
970 		const vk::VkQueue					queue				(getQueue(vkd, *device, queueFamilyIndex));
971 
972 		const vk::Unique<vk::VkSemaphore>	semaphoreA			(createExportableSemaphore(vkd, *device, config.externalType));
973 		NativeHandle						handle;
974 
975 		getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
976 
977 		submitDummySignal(vkd, queue, *semaphoreA);
978 		{
979 			{
980 				const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
981 
982 				submitDummyWait(vkd, queue, *semaphoreB);
983 				VK_CHECK(vkd.queueWaitIdle(queue));
984 			}
985 		}
986 
987 		return tcu::TestStatus::pass("Pass");
988 	}
989 }
990 
testSemaphoreExportImportSignalWait(Context & context,const SemaphoreTestConfig config)991 tcu::TestStatus testSemaphoreExportImportSignalWait (Context&					context,
992 													 const SemaphoreTestConfig	config)
993 {
994 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
995 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
996 	const vk::InstanceDriver			vki					(vkp, *instance);
997 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
998 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
999 
1000 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1001 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1002 
1003 	{
1004 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1005 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1006 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1007 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1008 
1009 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1010 		NativeHandle						handle;
1011 
1012 		submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1013 
1014 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1015 
1016 		submitDummySignal(vkd, queue, *semaphoreA);
1017 		submitDummyWait(vkd, queue, *semaphoreB);
1018 
1019 		VK_CHECK(vkd.queueWaitIdle(queue));
1020 
1021 		return tcu::TestStatus::pass("Pass");
1022 	}
1023 }
1024 
testSemaphoreSignalImport(Context & context,const SemaphoreTestConfig config)1025 tcu::TestStatus testSemaphoreSignalImport (Context&						context,
1026 										   const SemaphoreTestConfig	config)
1027 {
1028 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1029 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1030 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1031 	const vk::InstanceDriver			vki					(vkp, *instance);
1032 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1033 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1034 
1035 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1036 
1037 	{
1038 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1039 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1040 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1041 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1042 
1043 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1044 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createSemaphore(vkd, *device));
1045 		NativeHandle						handle;
1046 
1047 		submitDummySignal(vkd, queue, *semaphoreB);
1048 		VK_CHECK(vkd.queueWaitIdle(queue));
1049 
1050 		if (transference == TRANSFERENCE_COPY)
1051 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1052 		else
1053 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1054 
1055 		importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1056 
1057 		if (transference == TRANSFERENCE_COPY)
1058 			submitDummyWait(vkd, queue, *semaphoreB);
1059 		else if (transference == TRANSFERENCE_REFERENCE)
1060 		{
1061 			submitDummySignal(vkd, queue, *semaphoreA);
1062 			submitDummyWait(vkd, queue, *semaphoreB);
1063 		}
1064 		else
1065 			DE_FATAL("Unknown transference.");
1066 
1067 		VK_CHECK(vkd.queueWaitIdle(queue));
1068 
1069 		return tcu::TestStatus::pass("Pass");
1070 	}
1071 }
1072 
testSemaphoreSignalWaitImport(Context & context,const SemaphoreTestConfig config)1073 tcu::TestStatus testSemaphoreSignalWaitImport (Context&						context,
1074 											   const SemaphoreTestConfig	config)
1075 {
1076 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1077 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1078 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1079 	const vk::InstanceDriver			vki					(vkp, *instance);
1080 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1081 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1082 
1083 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1084 
1085 	{
1086 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1087 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1088 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1089 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1090 
1091 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1092 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createSemaphore(vkd, *device));
1093 		NativeHandle						handle;
1094 
1095 		if (transference == TRANSFERENCE_COPY)
1096 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1097 		else
1098 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1099 
1100 		submitDummySignal(vkd, queue, *semaphoreB);
1101 		submitDummyWait(vkd, queue, *semaphoreB);
1102 
1103 		VK_CHECK(vkd.queueWaitIdle(queue));
1104 
1105 		importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1106 
1107 		if (transference == TRANSFERENCE_COPY)
1108 			submitDummyWait(vkd, queue, *semaphoreB);
1109 		else if (transference == TRANSFERENCE_REFERENCE)
1110 		{
1111 			submitDummySignal(vkd, queue, *semaphoreA);
1112 			submitDummyWait(vkd, queue, *semaphoreB);
1113 		}
1114 		else
1115 			DE_FATAL("Unknown transference.");
1116 
1117 		VK_CHECK(vkd.queueWaitIdle(queue));
1118 
1119 		return tcu::TestStatus::pass("Pass");
1120 	}
1121 }
1122 
testSemaphoreMultipleExports(Context & context,const SemaphoreTestConfig config)1123 tcu::TestStatus testSemaphoreMultipleExports (Context&					context,
1124 											  const SemaphoreTestConfig	config)
1125 {
1126 	const size_t						exportCount			= 4 * 1024;
1127 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1128 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1129 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1130 	const vk::InstanceDriver			vki					(vkp, *instance);
1131 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1132 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1133 
1134 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1135 
1136 	{
1137 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1138 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1139 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1140 		const vk::Unique<vk::VkSemaphore>	semaphore	(createExportableSemaphore(vkd, *device, config.externalType));
1141 
1142 		for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1143 		{
1144 			NativeHandle handle;
1145 
1146 			if (transference == TRANSFERENCE_COPY)
1147 				submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1148 			else
1149 				getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1150 		}
1151 
1152 		submitDummySignal(vkd, queue, *semaphore);
1153 		submitDummyWait(vkd, queue, *semaphore);
1154 
1155 		VK_CHECK(vkd.queueWaitIdle(queue));
1156 	}
1157 
1158 	return tcu::TestStatus::pass("Pass");
1159 }
1160 
testSemaphoreMultipleImports(Context & context,const SemaphoreTestConfig config)1161 tcu::TestStatus testSemaphoreMultipleImports (Context&					context,
1162 											  const SemaphoreTestConfig	config)
1163 {
1164 	const size_t						importCount			= 4 * 1024;
1165 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1166 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1167 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1168 	const vk::InstanceDriver			vki					(vkp, *instance);
1169 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1170 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1171 
1172 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1173 
1174 	{
1175 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1176 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1177 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1178 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1179 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1180 		NativeHandle						handleA;
1181 
1182 		if (transference == TRANSFERENCE_COPY)
1183 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1184 		else
1185 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1186 
1187 		for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1188 		{
1189 			NativeHandle						handleB		(handleA);
1190 			const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1191 		}
1192 
1193 		if (transference == TRANSFERENCE_COPY)
1194 		{
1195 			importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1196 			submitDummyWait(vkd, queue, *semaphoreA);
1197 		}
1198 		else if (transference == TRANSFERENCE_REFERENCE)
1199 		{
1200 			submitDummySignal(vkd, queue, *semaphoreA);
1201 			submitDummyWait(vkd, queue, *semaphoreA);
1202 		}
1203 		else
1204 			DE_FATAL("Unknown transference.");
1205 
1206 		VK_CHECK(vkd.queueWaitIdle(queue));
1207 	}
1208 
1209 	return tcu::TestStatus::pass("Pass");
1210 }
1211 
testSemaphoreTransference(Context & context,const SemaphoreTestConfig config)1212 tcu::TestStatus testSemaphoreTransference (Context&						context,
1213 										   const SemaphoreTestConfig	config)
1214 {
1215 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1216 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1217 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1218 	const vk::InstanceDriver			vki					(vkp, *instance);
1219 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1220 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1221 
1222 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1223 
1224 	{
1225 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1226 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(),  vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1227 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1228 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1229 
1230 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1231 		NativeHandle						handle;
1232 
1233 		submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1234 
1235 		{
1236 			const vk::Unique<vk::VkSemaphore>	semaphoreB			(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1237 
1238 			if (config.permanence == PERMANENCE_PERMANENT)
1239 			{
1240 				if (transference == TRANSFERENCE_COPY)
1241 				{
1242 					submitDummySignal(vkd, queue, *semaphoreA);
1243 					submitDummyWait(vkd, queue, *semaphoreB);
1244 					VK_CHECK(vkd.queueWaitIdle(queue));
1245 
1246 					submitDummySignal(vkd, queue, *semaphoreB);
1247 
1248 					submitDummyWait(vkd, queue, *semaphoreA);
1249 					submitDummyWait(vkd, queue, *semaphoreB);
1250 					VK_CHECK(vkd.queueWaitIdle(queue));
1251 				}
1252 				else if (transference== TRANSFERENCE_REFERENCE)
1253 				{
1254 					submitDummyWait(vkd, queue, *semaphoreB);
1255 					VK_CHECK(vkd.queueWaitIdle(queue));
1256 
1257 					submitDummySignal(vkd, queue, *semaphoreA);
1258 					submitDummyWait(vkd, queue, *semaphoreB);
1259 
1260 					submitDummySignal(vkd, queue, *semaphoreB);
1261 					submitDummyWait(vkd, queue, *semaphoreA);
1262 					VK_CHECK(vkd.queueWaitIdle(queue));
1263 				}
1264 				else
1265 					DE_FATAL("Unknown transference.");
1266 			}
1267 			else if (config.permanence == PERMANENCE_TEMPORARY)
1268 			{
1269 				if (transference == TRANSFERENCE_COPY)
1270 				{
1271 					submitDummySignal(vkd, queue, *semaphoreA);
1272 					submitDummyWait(vkd, queue, *semaphoreB);
1273 					VK_CHECK(vkd.queueWaitIdle(queue));
1274 
1275 					submitDummySignal(vkd, queue, *semaphoreB);
1276 
1277 					submitDummyWait(vkd, queue, *semaphoreA);
1278 					submitDummyWait(vkd, queue, *semaphoreB);
1279 					VK_CHECK(vkd.queueWaitIdle(queue));
1280 				}
1281 				else if (transference== TRANSFERENCE_REFERENCE)
1282 				{
1283 					submitDummyWait(vkd, queue, *semaphoreB);
1284 					VK_CHECK(vkd.queueWaitIdle(queue));
1285 
1286 					submitDummySignal(vkd, queue, *semaphoreA);
1287 					submitDummySignal(vkd, queue, *semaphoreB);
1288 
1289 					submitDummyWait(vkd, queue, *semaphoreB);
1290 					submitDummyWait(vkd, queue, *semaphoreA);
1291 					VK_CHECK(vkd.queueWaitIdle(queue));
1292 				}
1293 				else
1294 					DE_FATAL("Unknown transference.");
1295 			}
1296 			else
1297 				DE_FATAL("Unknown permanence.");
1298 		}
1299 
1300 		return tcu::TestStatus::pass("Pass");
1301 	}
1302 }
1303 
testSemaphoreFdDup(Context & context,const SemaphoreTestConfig config)1304 tcu::TestStatus testSemaphoreFdDup (Context&					context,
1305 									const SemaphoreTestConfig	config)
1306 {
1307 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1308 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1309 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1310 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1311 	const vk::InstanceDriver			vki					(vkp, *instance);
1312 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1313 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1314 
1315 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1316 
1317 	{
1318 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1319 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1320 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1321 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1322 
1323 		TestLog&							log			= context.getTestContext().getLog();
1324 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1325 
1326 		{
1327 			NativeHandle		fd;
1328 
1329 			if (transference == TRANSFERENCE_COPY)
1330 				submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1331 			else
1332 				getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1333 
1334 			NativeHandle		newFd	(dup(fd.getFd()));
1335 
1336 			if (newFd.getFd() < 0)
1337 				log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1338 
1339 			TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1340 
1341 			{
1342 				const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1343 
1344 				if (transference == TRANSFERENCE_COPY)
1345 					submitDummyWait(vkd, queue, *semaphoreB);
1346 				else if (transference == TRANSFERENCE_REFERENCE)
1347 				{
1348 					submitDummySignal(vkd, queue, *semaphoreA);
1349 					submitDummyWait(vkd, queue, *semaphoreB);
1350 				}
1351 				else
1352 					DE_FATAL("Unknown permanence.");
1353 
1354 				VK_CHECK(vkd.queueWaitIdle(queue));
1355 			}
1356 		}
1357 
1358 		return tcu::TestStatus::pass("Pass");
1359 	}
1360 #else
1361 	DE_UNREF(context);
1362 	DE_UNREF(config);
1363 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1364 #endif
1365 }
1366 
testSemaphoreFdDup2(Context & context,const SemaphoreTestConfig config)1367 tcu::TestStatus testSemaphoreFdDup2 (Context&					context,
1368 									 const SemaphoreTestConfig	config)
1369 {
1370 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1371 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1372 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1373 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1374 	const vk::InstanceDriver			vki					(vkp, *instance);
1375 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1376 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1377 
1378 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1379 
1380 	{
1381 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1382 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1383 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1384 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1385 
1386 		TestLog&							log			= context.getTestContext().getLog();
1387 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1388 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createExportableSemaphore(vkd, *device, config.externalType));
1389 
1390 		{
1391 			NativeHandle		fd, secondFd;
1392 
1393 			if (transference == TRANSFERENCE_COPY)
1394 			{
1395 				submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1396 				submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1397 			}
1398 			else
1399 			{
1400 				getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1401 				getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1402 			}
1403 
1404 			int					newFd		(dup2(fd.getFd(), secondFd.getFd()));
1405 
1406 			if (newFd < 0)
1407 				log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1408 
1409 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1410 
1411 			{
1412 				const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1413 
1414 				if (transference == TRANSFERENCE_COPY)
1415 					submitDummyWait(vkd, queue, *semaphoreC);
1416 				else if (transference == TRANSFERENCE_REFERENCE)
1417 				{
1418 					submitDummySignal(vkd, queue, *semaphoreA);
1419 					submitDummyWait(vkd, queue, *semaphoreC);
1420 				}
1421 				else
1422 					DE_FATAL("Unknown permanence.");
1423 
1424 				VK_CHECK(vkd.queueWaitIdle(queue));
1425 			}
1426 		}
1427 
1428 		return tcu::TestStatus::pass("Pass");
1429 	}
1430 #else
1431 	DE_UNREF(context);
1432 	DE_UNREF(config);
1433 	TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1434 #endif
1435 }
1436 
testSemaphoreFdDup3(Context & context,const SemaphoreTestConfig config)1437 tcu::TestStatus testSemaphoreFdDup3 (Context&					context,
1438 									 const SemaphoreTestConfig	config)
1439 {
1440 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1441 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1442 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1443 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1444 	const vk::InstanceDriver			vki					(vkp, *instance);
1445 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1446 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1447 
1448 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1449 
1450 	{
1451 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1452 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1453 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1454 
1455 		TestLog&							log			= context.getTestContext().getLog();
1456 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1457 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createExportableSemaphore(vkd, *device, config.externalType));
1458 
1459 		{
1460 			NativeHandle						fd, secondFd;
1461 
1462 			if (transference == TRANSFERENCE_COPY)
1463 			{
1464 				submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1465 				submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1466 			}
1467 			else
1468 			{
1469 				getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1470 				getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1471 			}
1472 
1473 			const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1474 			const int							newFd		(dup3(fd.getFd(), secondFd.getFd(), 0));
1475 
1476 			if (newFd < 0)
1477 				log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1478 
1479 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1480 
1481 			{
1482 				const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1483 
1484 				if (transference == TRANSFERENCE_COPY)
1485 					submitDummyWait(vkd, queue, *semaphoreC);
1486 				else if (transference == TRANSFERENCE_REFERENCE)
1487 				{
1488 					submitDummySignal(vkd, queue, *semaphoreA);
1489 					submitDummyWait(vkd, queue, *semaphoreC);
1490 				}
1491 				else
1492 					DE_FATAL("Unknown permanence.");
1493 
1494 				VK_CHECK(vkd.queueWaitIdle(queue));
1495 			}
1496 		}
1497 
1498 		return tcu::TestStatus::pass("Pass");
1499 	}
1500 #else
1501 	DE_UNREF(context);
1502 	DE_UNREF(config);
1503 	TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1504 #endif
1505 }
1506 
testSemaphoreFdSendOverSocket(Context & context,const SemaphoreTestConfig config)1507 tcu::TestStatus testSemaphoreFdSendOverSocket (Context&						context,
1508 											   const SemaphoreTestConfig	config)
1509 {
1510 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1511 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1512 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1513 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), config.externalType, 0u, 0u));
1514 	const vk::InstanceDriver			vki					(vkp, *instance);
1515 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1516 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1517 
1518 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1519 
1520 	{
1521 		const vk::Unique<vk::VkDevice>		device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1522 		const vk::DeviceDriver				vkd			(vkp, *instance, *device);
1523 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1524 
1525 		TestLog&							log			= context.getTestContext().getLog();
1526 		const vk::Unique<vk::VkSemaphore>	semaphore	(createExportableSemaphore(vkd, *device, config.externalType));
1527 		NativeHandle						fd;
1528 
1529 		if (transference == TRANSFERENCE_COPY)
1530 			submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1531 		else
1532 			getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1533 
1534 		{
1535 			int sv[2];
1536 
1537 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1538 			{
1539 				log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1540 				TCU_FAIL("Failed to create socket pair");
1541 			}
1542 
1543 			{
1544 				const NativeHandle	srcSocket	(sv[0]);
1545 				const NativeHandle	dstSocket	(sv[1]);
1546 				std::string			sendData	("deqp");
1547 
1548 				// Send FD
1549 				{
1550 					const int			fdRaw	(fd.getFd());
1551 					msghdr				msg;
1552 					cmsghdr*			cmsg;
1553 					char				buffer[CMSG_SPACE(sizeof(int))];
1554 					iovec				iov		= { &sendData[0], sendData.length()};
1555 
1556 					deMemset(&msg, 0, sizeof(msg));
1557 
1558 					msg.msg_control		= buffer;
1559 					msg.msg_controllen	= sizeof(buffer);
1560 					msg.msg_iovlen		= 1;
1561 					msg.msg_iov			= &iov;
1562 
1563 					cmsg				= CMSG_FIRSTHDR(&msg);
1564 					cmsg->cmsg_level	= SOL_SOCKET;
1565 					cmsg->cmsg_type		= SCM_RIGHTS;
1566 					cmsg->cmsg_len		= CMSG_LEN(sizeof(int));
1567 
1568 					deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1569 					msg.msg_controllen = cmsg->cmsg_len;
1570 
1571 					if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1572 					{
1573 						log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1574 						TCU_FAIL("Failed to send fd over socket");
1575 					}
1576 				}
1577 
1578 				// Recv FD
1579 				{
1580 					msghdr			msg;
1581 					char			buffer[CMSG_SPACE(sizeof(int))];
1582 					std::string		recvData	(4, '\0');
1583 					iovec			iov			= { &recvData[0], recvData.length() };
1584 
1585 					deMemset(&msg, 0, sizeof(msg));
1586 
1587 					msg.msg_control		= buffer;
1588 					msg.msg_controllen	= sizeof(buffer);
1589 					msg.msg_iovlen		= 1;
1590 					msg.msg_iov			= &iov;
1591 
1592 					const ssize_t	bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1593 
1594 					if (bytes < 0)
1595 					{
1596 						log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1597 						TCU_FAIL("Failed to recv fd over socket");
1598 
1599 					}
1600 					else if (bytes != (ssize_t)sendData.length())
1601 					{
1602 						TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1603 					}
1604 					else
1605 					{
1606 						const vk::VkSemaphoreImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1607 						const cmsghdr* const				cmsg	= CMSG_FIRSTHDR(&msg);
1608 						int									newFd_;
1609 						deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1610 						NativeHandle						newFd	(newFd_);
1611 
1612 						TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1613 						TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1614 						TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1615 						TCU_CHECK(recvData == sendData);
1616 						TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1617 
1618 						{
1619 							const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1620 
1621 							if (transference == TRANSFERENCE_COPY)
1622 								submitDummyWait(vkd, queue, *newSemaphore);
1623 							else if (transference == TRANSFERENCE_REFERENCE)
1624 							{
1625 								submitDummySignal(vkd, queue, *newSemaphore);
1626 								submitDummyWait(vkd, queue, *newSemaphore);
1627 							}
1628 							else
1629 								DE_FATAL("Unknown permanence.");
1630 
1631 							VK_CHECK(vkd.queueWaitIdle(queue));
1632 						}
1633 					}
1634 				}
1635 			}
1636 		}
1637 	}
1638 
1639 	return tcu::TestStatus::pass("Pass");
1640 #else
1641 	DE_UNREF(context);
1642 	DE_UNREF(config);
1643 	TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1644 #endif
1645 }
1646 
testFenceQueries(Context & context,vk::VkExternalFenceHandleTypeFlagBits externalType)1647 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1648 {
1649 	const vk::PlatformInterface&					vkp			(context.getPlatformInterface());
1650 	const vk::Unique<vk::VkInstance>				instance	(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, externalType));
1651 	const vk::InstanceDriver						vki			(vkp, *instance);
1652 	const vk::VkPhysicalDevice						device		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1653 
1654 	TestLog&										log			= context.getTestContext().getLog();
1655 
1656 	const vk::VkPhysicalDeviceExternalFenceInfo		info		=
1657 	{
1658 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1659 		DE_NULL,
1660 		externalType
1661 	};
1662 	vk::VkExternalFenceProperties					properties	=
1663 	{
1664 		vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1665 		DE_NULL,
1666 		0u,
1667 		0u,
1668 		0u
1669 	};
1670 
1671 	vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1672 	log << TestLog::Message << properties << TestLog::EndMessage;
1673 
1674 	TCU_CHECK(properties.pNext == DE_NULL);
1675 	TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1676 
1677 	return tcu::TestStatus::pass("Pass");
1678 }
1679 
1680 struct FenceTestConfig
1681 {
FenceTestConfigvkt::api::__anon041f48660111::FenceTestConfig1682 												FenceTestConfig	(vk::VkExternalFenceHandleTypeFlagBits	externalType_,
1683 																 Permanence									permanence_)
1684 		: externalType		(externalType_)
1685 		, permanence		(permanence_)
1686 	{
1687 	}
1688 
1689 	vk::VkExternalFenceHandleTypeFlagBits	externalType;
1690 	Permanence								permanence;
1691 };
1692 
1693 
testFenceWin32Create(Context & context,const FenceTestConfig config)1694 tcu::TestStatus testFenceWin32Create (Context&				context,
1695 									  const FenceTestConfig	config)
1696 {
1697 #if (DE_OS == DE_OS_WIN32)
1698 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1699 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1700 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1701 	const vk::InstanceDriver			vki					(vkp, *instance);
1702 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1703 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1704 
1705 	checkFenceSupport(vki, physicalDevice, config.externalType);
1706 
1707 	{
1708 		const vk::Unique<vk::VkDevice>				device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1709 		const vk::DeviceDriver						vkd				(vkp, *instance, *device);
1710 		const vk::VkQueue							queue			(getQueue(vkd, *device, queueFamilyIndex));
1711 		const vk::VkExportFenceWin32HandleInfoKHR	win32ExportInfo	=
1712 		{
1713 			vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1714 			DE_NULL,
1715 
1716 			(vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1717 			DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1718 			DE_NULL
1719 		};
1720 		const vk::VkExportFenceCreateInfo			exportCreateInfo=
1721 		{
1722 			vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1723 			&win32ExportInfo,
1724 			(vk::VkExternalFenceHandleTypeFlags)config.externalType
1725 		};
1726 		const vk::VkFenceCreateInfo					createInfo		=
1727 		{
1728 			vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1729 			&exportCreateInfo,
1730 			0u
1731 		};
1732 		const vk::Unique<vk::VkFence>				fence			(vk::createFence(vkd, *device, &createInfo));
1733 
1734 		if (transference == TRANSFERENCE_COPY)
1735 			submitDummySignal(vkd, queue, *fence);
1736 
1737 		NativeHandle								handleA;
1738 		getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1739 
1740 		{
1741 			const vk::VkFenceImportFlags			flags			= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1742 			const vk::Unique<vk::VkFence>			fenceA			(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1743 
1744 			if (transference == TRANSFERENCE_COPY)
1745 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1746 			else if (transference == TRANSFERENCE_REFERENCE)
1747 			{
1748 				submitDummySignal(vkd, queue, *fence);
1749 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1750 			}
1751 			else
1752 				DE_FATAL("Unknown transference.");
1753 
1754 			VK_CHECK(vkd.queueWaitIdle(queue));
1755 		}
1756 
1757 		return tcu::TestStatus::pass("Pass");
1758 	}
1759 #else
1760 	DE_UNREF(context);
1761 	DE_UNREF(config);
1762 	TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1763 #endif
1764 }
1765 
testFenceImportTwice(Context & context,const FenceTestConfig config)1766 tcu::TestStatus testFenceImportTwice (Context&				context,
1767 									  const FenceTestConfig	config)
1768 {
1769 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1770 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1771 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1772 	const vk::InstanceDriver			vki					(vkp, *instance);
1773 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1774 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1775 
1776 	checkFenceSupport(vki, physicalDevice, config.externalType);
1777 
1778 	{
1779 		const vk::Unique<vk::VkDevice>	device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1780 		const vk::DeviceDriver			vkd			(vkp, *instance, *device);
1781 		const vk::VkQueue				queue		(getQueue(vkd, *device, queueFamilyIndex));
1782 		const vk::Unique<vk::VkFence>	fence		(createExportableFence(vkd, *device, config.externalType));
1783 		NativeHandle					handleA;
1784 
1785 		if (transference == TRANSFERENCE_COPY)
1786 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1787 		else
1788 			getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1789 
1790 		{
1791 			NativeHandle					handleB	(handleA);
1792 			const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1793 			const vk::Unique<vk::VkFence>	fenceA	(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1794 			const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1795 
1796 			if (transference == TRANSFERENCE_COPY)
1797 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1798 			else if (transference == TRANSFERENCE_REFERENCE)
1799 			{
1800 				submitDummySignal(vkd, queue, *fenceA);
1801 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1802 			}
1803 			else
1804 				DE_FATAL("Unknown transference.");
1805 
1806 			VK_CHECK(vkd.queueWaitIdle(queue));
1807 		}
1808 
1809 		return tcu::TestStatus::pass("Pass");
1810 	}
1811 }
1812 
testFenceImportReimport(Context & context,const FenceTestConfig config)1813 tcu::TestStatus testFenceImportReimport (Context&				context,
1814 										 const FenceTestConfig	config)
1815 {
1816 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1817 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1818 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1819 	const vk::InstanceDriver			vki					(vkp, *instance);
1820 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1821 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1822 
1823 	checkFenceSupport(vki, physicalDevice, config.externalType);
1824 
1825 	{
1826 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1827 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
1828 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
1829 
1830 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
1831 		NativeHandle					handleA;
1832 
1833 		if (transference == TRANSFERENCE_COPY)
1834 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1835 		else
1836 			getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1837 
1838 		NativeHandle					handleB	(handleA);
1839 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1840 		const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1841 
1842 		importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1843 
1844 		if (transference == TRANSFERENCE_COPY)
1845 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1846 		else if (transference == TRANSFERENCE_REFERENCE)
1847 		{
1848 			submitDummySignal(vkd, queue, *fenceA);
1849 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1850 		}
1851 		else
1852 			DE_FATAL("Unknown transference.");
1853 
1854 		VK_CHECK(vkd.queueWaitIdle(queue));
1855 
1856 		return tcu::TestStatus::pass("Pass");
1857 	}
1858 }
1859 
testFenceSignalExportImportWait(Context & context,const FenceTestConfig config)1860 tcu::TestStatus testFenceSignalExportImportWait (Context&				context,
1861 												 const FenceTestConfig	config)
1862 {
1863 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1864 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1865 	const vk::InstanceDriver			vki					(vkp, *instance);
1866 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1867 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1868 
1869 	checkFenceSupport(vki, physicalDevice, config.externalType);
1870 
1871 	{
1872 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1873 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
1874 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
1875 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
1876 
1877 		{
1878 			NativeHandle	handle;
1879 
1880 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1881 
1882 			{
1883 				const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1884 				const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
1885 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1886 
1887 				VK_CHECK(vkd.queueWaitIdle(queue));
1888 			}
1889 		}
1890 
1891 		return tcu::TestStatus::pass("Pass");
1892 	}
1893 }
1894 
testFenceExportSignalImportWait(Context & context,const FenceTestConfig config)1895 tcu::TestStatus testFenceExportSignalImportWait (Context&				context,
1896 												 const FenceTestConfig	config)
1897 {
1898 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1899 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1900 	const vk::InstanceDriver			vki					(vkp, *instance);
1901 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1902 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1903 	const vk::VkFenceImportFlags		flags				= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1904 
1905 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1906 	checkFenceSupport(vki, physicalDevice, config.externalType);
1907 
1908 	{
1909 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1910 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
1911 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
1912 
1913 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
1914 		NativeHandle					handle;
1915 
1916 		getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1917 
1918 		submitDummySignal(vkd, queue, *fenceA);
1919 		{
1920 			{
1921 				const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
1922 
1923 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1924 				VK_CHECK(vkd.queueWaitIdle(queue));
1925 			}
1926 		}
1927 
1928 		return tcu::TestStatus::pass("Pass");
1929 	}
1930 }
1931 
testFenceExportImportSignalWait(Context & context,const FenceTestConfig config)1932 tcu::TestStatus testFenceExportImportSignalWait (Context&				context,
1933 												 const FenceTestConfig	config)
1934 {
1935 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1936 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1937 	const vk::InstanceDriver			vki					(vkp, *instance);
1938 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1939 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1940 
1941 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1942 	checkFenceSupport(vki, physicalDevice, config.externalType);
1943 
1944 	{
1945 		const vk::VkFenceImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1946 		const vk::Unique<vk::VkDevice>	device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1947 		const vk::DeviceDriver			vkd			(vkp, *instance, *device);
1948 		const vk::VkQueue				queue		(getQueue(vkd, *device, queueFamilyIndex));
1949 
1950 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
1951 		NativeHandle					handle;
1952 
1953 		getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1954 
1955 		const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
1956 
1957 		submitDummySignal(vkd, queue, *fenceA);
1958 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1959 
1960 		VK_CHECK(vkd.queueWaitIdle(queue));
1961 
1962 		return tcu::TestStatus::pass("Pass");
1963 	}
1964 }
1965 
testFenceSignalImport(Context & context,const FenceTestConfig config)1966 tcu::TestStatus testFenceSignalImport (Context&					context,
1967 									   const FenceTestConfig	config)
1968 {
1969 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1970 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1971 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
1972 	const vk::InstanceDriver			vki					(vkp, *instance);
1973 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
1974 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1975 
1976 	checkFenceSupport(vki, physicalDevice, config.externalType);
1977 
1978 	{
1979 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1980 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1981 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
1982 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
1983 
1984 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
1985 		const vk::Unique<vk::VkFence>	fenceB	(createFence(vkd, *device));
1986 		NativeHandle					handle;
1987 
1988 		submitDummySignal(vkd, queue, *fenceB);
1989 		VK_CHECK(vkd.queueWaitIdle(queue));
1990 
1991 		if (transference == TRANSFERENCE_COPY)
1992 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1993 		else
1994 			getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1995 
1996 		importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
1997 
1998 		if (transference == TRANSFERENCE_COPY)
1999 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2000 		else if (transference == TRANSFERENCE_REFERENCE)
2001 		{
2002 			submitDummySignal(vkd, queue, *fenceA);
2003 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2004 		}
2005 		else
2006 			DE_FATAL("Unknown transference.");
2007 
2008 		VK_CHECK(vkd.queueWaitIdle(queue));
2009 
2010 		return tcu::TestStatus::pass("Pass");
2011 	}
2012 }
2013 
testFenceReset(Context & context,const FenceTestConfig config)2014 tcu::TestStatus testFenceReset (Context&				context,
2015 								const FenceTestConfig	config)
2016 {
2017 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2018 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2019 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2020 	const vk::InstanceDriver			vki					(vkp, *instance);
2021 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2022 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2023 
2024 	checkFenceSupport(vki, physicalDevice, config.externalType);
2025 
2026 	{
2027 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2028 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2029 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2030 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2031 
2032 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2033 		const vk::Unique<vk::VkFence>	fenceB	(createFence(vkd, *device));
2034 		const vk::Unique<vk::VkFence>	fenceC	(createFence(vkd, *device));
2035 		NativeHandle					handle;
2036 
2037 		submitDummySignal(vkd, queue, *fenceB);
2038 		VK_CHECK(vkd.queueWaitIdle(queue));
2039 
2040 		submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2041 		NativeHandle					handleB	(handle);
2042 		importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2043 		importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2044 
2045 		VK_CHECK(vkd.queueWaitIdle(queue));
2046 		VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2047 
2048 		if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2049 		{
2050 			// vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2051 			// or fenceB should be separate copy of the payload and not affect fenceC
2052 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2053 
2054 			// vkResetFences() should have restored fenceBs prior state and should be now reset
2055 			// or fenceB should have it's separate payload
2056 			submitDummySignal(vkd, queue, *fenceB);
2057 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2058 		}
2059 		else if (config.permanence == PERMANENCE_PERMANENT)
2060 		{
2061 			DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2062 
2063 			// Reset fences should have reset all of the fences
2064 			submitDummySignal(vkd, queue, *fenceC);
2065 
2066 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2067 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2068 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2069 		}
2070 		else
2071 			DE_FATAL("Unknown permanence");
2072 
2073 		VK_CHECK(vkd.queueWaitIdle(queue));
2074 
2075 		return tcu::TestStatus::pass("Pass");
2076 	}
2077 }
2078 
testFenceSignalWaitImport(Context & context,const FenceTestConfig config)2079 tcu::TestStatus testFenceSignalWaitImport (Context&					context,
2080 										   const FenceTestConfig	config)
2081 {
2082 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2083 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2084 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2085 	const vk::InstanceDriver			vki					(vkp, *instance);
2086 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2087 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2088 
2089 	checkFenceSupport(vki, physicalDevice, config.externalType);
2090 
2091 	{
2092 		const vk::VkFenceImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2093 		const vk::Unique<vk::VkDevice>	device		(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2094 		const vk::DeviceDriver			vkd			(vkp, *instance, *device);
2095 		const vk::VkQueue				queue		(getQueue(vkd, *device, queueFamilyIndex));
2096 
2097 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2098 		const vk::Unique<vk::VkFence>	fenceB	(createFence(vkd, *device));
2099 		NativeHandle					handle;
2100 
2101 		if (transference == TRANSFERENCE_COPY)
2102 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2103 		else
2104 			getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2105 
2106 		submitDummySignal(vkd, queue, *fenceB);
2107 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2108 
2109 		VK_CHECK(vkd.queueWaitIdle(queue));
2110 
2111 		importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2112 
2113 		if (transference == TRANSFERENCE_COPY)
2114 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2115 		else if (transference == TRANSFERENCE_REFERENCE)
2116 		{
2117 			submitDummySignal(vkd, queue, *fenceA);
2118 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2119 		}
2120 		else
2121 			DE_FATAL("Unknown transference.");
2122 
2123 		VK_CHECK(vkd.queueWaitIdle(queue));
2124 
2125 		return tcu::TestStatus::pass("Pass");
2126 	}
2127 }
2128 
testFenceMultipleExports(Context & context,const FenceTestConfig config)2129 tcu::TestStatus testFenceMultipleExports (Context&				context,
2130 										  const FenceTestConfig	config)
2131 {
2132 	const size_t						exportCount			= 4 * 1024;
2133 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2134 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2135 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2136 	const vk::InstanceDriver			vki					(vkp, *instance);
2137 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2138 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2139 
2140 	checkFenceSupport(vki, physicalDevice, config.externalType);
2141 
2142 	{
2143 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2144 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2145 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2146 		const vk::Unique<vk::VkFence>	fence	(createExportableFence(vkd, *device, config.externalType));
2147 
2148 		for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2149 		{
2150 			NativeHandle handle;
2151 
2152 			if (transference == TRANSFERENCE_COPY)
2153 				submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle);
2154 			else
2155 				getFenceNative(vkd, *device, *fence, config.externalType, handle);
2156 		}
2157 
2158 		submitDummySignal(vkd, queue, *fence);
2159 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2160 
2161 		VK_CHECK(vkd.queueWaitIdle(queue));
2162 	}
2163 
2164 	return tcu::TestStatus::pass("Pass");
2165 }
2166 
testFenceMultipleImports(Context & context,const FenceTestConfig config)2167 tcu::TestStatus testFenceMultipleImports (Context&				context,
2168 										  const FenceTestConfig	config)
2169 {
2170 	const size_t						importCount			= 4 * 1024;
2171 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2172 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2173 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2174 	const vk::InstanceDriver			vki					(vkp, *instance);
2175 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2176 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2177 
2178 	checkFenceSupport(vki, physicalDevice, config.externalType);
2179 
2180 	{
2181 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2182 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2183 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2184 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2185 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2186 		NativeHandle					handleA;
2187 
2188 		if (transference == TRANSFERENCE_COPY)
2189 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2190 		else
2191 			getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2192 
2193 		for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2194 		{
2195 			NativeHandle					handleB		(handleA);
2196 			const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2197 		}
2198 
2199 		if (transference == TRANSFERENCE_COPY)
2200 		{
2201 			importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2202 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2203 		}
2204 		else if (transference == TRANSFERENCE_REFERENCE)
2205 		{
2206 			submitDummySignal(vkd, queue, *fenceA);
2207 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2208 		}
2209 		else
2210 			DE_FATAL("Unknown transference.");
2211 
2212 		VK_CHECK(vkd.queueWaitIdle(queue));
2213 	}
2214 
2215 	return tcu::TestStatus::pass("Pass");
2216 }
2217 
testFenceTransference(Context & context,const FenceTestConfig config)2218 tcu::TestStatus testFenceTransference (Context&					context,
2219 									   const FenceTestConfig	config)
2220 {
2221 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2222 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2223 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2224 	const vk::InstanceDriver			vki					(vkp, *instance);
2225 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2226 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2227 
2228 	checkFenceSupport(vki, physicalDevice, config.externalType);
2229 
2230 	{
2231 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2232 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2233 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2234 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2235 
2236 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2237 		NativeHandle					handle;
2238 
2239 		submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2240 
2241 		{
2242 			const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2243 
2244 			if (config.permanence == PERMANENCE_PERMANENT)
2245 			{
2246 				if (transference == TRANSFERENCE_COPY)
2247 				{
2248 					submitDummySignal(vkd, queue, *fenceA);
2249 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2250 					VK_CHECK(vkd.queueWaitIdle(queue));
2251 
2252 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2253 					submitDummySignal(vkd, queue, *fenceB);
2254 
2255 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2256 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2257 					VK_CHECK(vkd.queueWaitIdle(queue));
2258 				}
2259 				else if (transference== TRANSFERENCE_REFERENCE)
2260 				{
2261 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2262 					VK_CHECK(vkd.queueWaitIdle(queue));
2263 
2264 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2265 					submitDummySignal(vkd, queue, *fenceA);
2266 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2267 
2268 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2269 					submitDummySignal(vkd, queue, *fenceB);
2270 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2271 					VK_CHECK(vkd.queueWaitIdle(queue));
2272 				}
2273 				else
2274 					DE_FATAL("Unknown transference.");
2275 			}
2276 			else if (config.permanence == PERMANENCE_TEMPORARY)
2277 			{
2278 				if (transference == TRANSFERENCE_COPY)
2279 				{
2280 					submitDummySignal(vkd, queue, *fenceA);
2281 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2282 					VK_CHECK(vkd.queueWaitIdle(queue));
2283 
2284 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2285 					submitDummySignal(vkd, queue, *fenceB);
2286 
2287 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2288 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2289 					VK_CHECK(vkd.queueWaitIdle(queue));
2290 				}
2291 				else if (transference == TRANSFERENCE_REFERENCE)
2292 				{
2293 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2294 					VK_CHECK(vkd.queueWaitIdle(queue));
2295 
2296 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2297 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2298 					submitDummySignal(vkd, queue, *fenceA);
2299 					submitDummySignal(vkd, queue, *fenceB);
2300 
2301 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2302 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2303 					VK_CHECK(vkd.queueWaitIdle(queue));
2304 				}
2305 				else
2306 					DE_FATAL("Unknown transference.");
2307 			}
2308 			else
2309 				DE_FATAL("Unknown permanence.");
2310 		}
2311 
2312 		return tcu::TestStatus::pass("Pass");
2313 	}
2314 }
2315 
testFenceFdDup(Context & context,const FenceTestConfig config)2316 tcu::TestStatus testFenceFdDup (Context&				context,
2317 								const FenceTestConfig	config)
2318 {
2319 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2320 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2321 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2322 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2323 	const vk::InstanceDriver			vki					(vkp, *instance);
2324 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2325 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2326 
2327 	checkFenceSupport(vki, physicalDevice, config.externalType);
2328 
2329 	{
2330 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2331 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2332 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2333 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2334 
2335 		TestLog&						log		= context.getTestContext().getLog();
2336 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2337 
2338 		{
2339 			NativeHandle		fd;
2340 
2341 			if (transference == TRANSFERENCE_COPY)
2342 				submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2343 			else
2344 				getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2345 
2346 			NativeHandle		newFd	(dup(fd.getFd()));
2347 
2348 			if (newFd.getFd() < 0)
2349 				log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2350 
2351 			TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2352 
2353 			{
2354 				const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2355 
2356 				if (transference == TRANSFERENCE_COPY)
2357 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2358 				else if (transference == TRANSFERENCE_REFERENCE)
2359 				{
2360 					submitDummySignal(vkd, queue, *fenceA);
2361 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2362 				}
2363 				else
2364 					DE_FATAL("Unknown permanence.");
2365 
2366 				VK_CHECK(vkd.queueWaitIdle(queue));
2367 			}
2368 		}
2369 
2370 		return tcu::TestStatus::pass("Pass");
2371 	}
2372 #else
2373 	DE_UNREF(context);
2374 	DE_UNREF(config);
2375 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2376 #endif
2377 }
2378 
testFenceFdDup2(Context & context,const FenceTestConfig config)2379 tcu::TestStatus testFenceFdDup2 (Context&				context,
2380 								 const FenceTestConfig	config)
2381 {
2382 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2383 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2384 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2385 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2386 	const vk::InstanceDriver			vki					(vkp, *instance);
2387 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2388 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2389 
2390 	checkFenceSupport(vki, physicalDevice, config.externalType);
2391 
2392 	{
2393 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2394 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2395 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2396 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2397 
2398 		TestLog&						log		= context.getTestContext().getLog();
2399 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2400 		const vk::Unique<vk::VkFence>	fenceB	(createExportableFence(vkd, *device, config.externalType));
2401 
2402 		{
2403 			NativeHandle		fd, secondFd;
2404 
2405 			if (transference == TRANSFERENCE_COPY)
2406 			{
2407 				submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2408 				submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2409 			}
2410 			else
2411 			{
2412 				getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2413 				getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2414 			}
2415 
2416 			int					newFd		(dup2(fd.getFd(), secondFd.getFd()));
2417 
2418 			if (newFd < 0)
2419 				log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2420 
2421 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2422 
2423 			{
2424 				const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2425 
2426 				if (transference == TRANSFERENCE_COPY)
2427 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2428 				else if (transference == TRANSFERENCE_REFERENCE)
2429 				{
2430 					submitDummySignal(vkd, queue, *fenceA);
2431 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2432 				}
2433 				else
2434 					DE_FATAL("Unknown permanence.");
2435 
2436 				VK_CHECK(vkd.queueWaitIdle(queue));
2437 			}
2438 		}
2439 
2440 		return tcu::TestStatus::pass("Pass");
2441 	}
2442 #else
2443 	DE_UNREF(context);
2444 	DE_UNREF(config);
2445 	TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2446 #endif
2447 }
2448 
testFenceFdDup3(Context & context,const FenceTestConfig config)2449 tcu::TestStatus testFenceFdDup3 (Context&				context,
2450 								 const FenceTestConfig	config)
2451 {
2452 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2453 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2454 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2455 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2456 	const vk::InstanceDriver			vki					(vkp, *instance);
2457 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2458 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2459 
2460 	checkFenceSupport(vki, physicalDevice, config.externalType);
2461 
2462 	{
2463 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2464 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2465 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2466 
2467 		TestLog&						log		= context.getTestContext().getLog();
2468 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2469 		const vk::Unique<vk::VkFence>	fenceB	(createExportableFence(vkd, *device, config.externalType));
2470 
2471 		{
2472 			NativeHandle					fd, secondFd;
2473 
2474 			if (transference == TRANSFERENCE_COPY)
2475 			{
2476 				submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2477 				submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2478 			}
2479 			else
2480 			{
2481 				getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2482 				getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2483 			}
2484 
2485 			const vk::VkFenceImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2486 			const int						newFd		(dup3(fd.getFd(), secondFd.getFd(), 0));
2487 
2488 			if (newFd < 0)
2489 				log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2490 
2491 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2492 
2493 			{
2494 				const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2495 
2496 				if (transference == TRANSFERENCE_COPY)
2497 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2498 				else if (transference == TRANSFERENCE_REFERENCE)
2499 				{
2500 					submitDummySignal(vkd, queue, *fenceA);
2501 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2502 				}
2503 				else
2504 					DE_FATAL("Unknown permanence.");
2505 
2506 				VK_CHECK(vkd.queueWaitIdle(queue));
2507 			}
2508 		}
2509 
2510 		return tcu::TestStatus::pass("Pass");
2511 	}
2512 #else
2513 	DE_UNREF(context);
2514 	DE_UNREF(config);
2515 	TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2516 #endif
2517 }
2518 
testFenceFdSendOverSocket(Context & context,const FenceTestConfig config)2519 tcu::TestStatus testFenceFdSendOverSocket (Context&					context,
2520 										   const FenceTestConfig	config)
2521 {
2522 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2523 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2524 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2525 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, 0u, config.externalType));
2526 	const vk::InstanceDriver			vki					(vkp, *instance);
2527 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2528 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2529 
2530 	checkFenceSupport(vki, physicalDevice, config.externalType);
2531 
2532 	{
2533 		const vk::Unique<vk::VkDevice>	device	(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2534 		const vk::DeviceDriver			vkd		(vkp, *instance, *device);
2535 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2536 
2537 		TestLog&						log		= context.getTestContext().getLog();
2538 		const vk::Unique<vk::VkFence>	fence	(createExportableFence(vkd, *device, config.externalType));
2539 		NativeHandle					fd;
2540 
2541 		if (transference == TRANSFERENCE_COPY)
2542 			submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2543 		else
2544 			getFenceNative(vkd, *device, *fence, config.externalType, fd);
2545 
2546 		{
2547 			int sv[2];
2548 
2549 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2550 			{
2551 				log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2552 				TCU_FAIL("Failed to create socket pair");
2553 			}
2554 
2555 			{
2556 				const NativeHandle	srcSocket	(sv[0]);
2557 				const NativeHandle	dstSocket	(sv[1]);
2558 				std::string			sendData	("deqp");
2559 
2560 				// Send FD
2561 				{
2562 					const int			fdRaw	(fd.getFd());
2563 					msghdr				msg;
2564 					cmsghdr*			cmsg;
2565 					char				buffer[CMSG_SPACE(sizeof(int))];
2566 					iovec				iov		= { &sendData[0], sendData.length()};
2567 
2568 					deMemset(&msg, 0, sizeof(msg));
2569 
2570 					msg.msg_control		= buffer;
2571 					msg.msg_controllen	= sizeof(buffer);
2572 					msg.msg_iovlen		= 1;
2573 					msg.msg_iov			= &iov;
2574 
2575 					cmsg				= CMSG_FIRSTHDR(&msg);
2576 					cmsg->cmsg_level	= SOL_SOCKET;
2577 					cmsg->cmsg_type		= SCM_RIGHTS;
2578 					cmsg->cmsg_len		= CMSG_LEN(sizeof(int));
2579 
2580 					deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2581 					msg.msg_controllen = cmsg->cmsg_len;
2582 
2583 					if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2584 					{
2585 						log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2586 						TCU_FAIL("Failed to send fd over socket");
2587 					}
2588 				}
2589 
2590 				// Recv FD
2591 				{
2592 					msghdr			msg;
2593 					char			buffer[CMSG_SPACE(sizeof(int))];
2594 					std::string		recvData	(4, '\0');
2595 					iovec			iov			= { &recvData[0], recvData.length() };
2596 
2597 					deMemset(&msg, 0, sizeof(msg));
2598 
2599 					msg.msg_control		= buffer;
2600 					msg.msg_controllen	= sizeof(buffer);
2601 					msg.msg_iovlen		= 1;
2602 					msg.msg_iov			= &iov;
2603 
2604 					const ssize_t	bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2605 
2606 					if (bytes < 0)
2607 					{
2608 						log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2609 						TCU_FAIL("Failed to recv fd over socket");
2610 
2611 					}
2612 					else if (bytes != (ssize_t)sendData.length())
2613 					{
2614 						TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2615 					}
2616 					else
2617 					{
2618 						const vk::VkFenceImportFlags		flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2619 						const cmsghdr* const				cmsg	= CMSG_FIRSTHDR(&msg);
2620 						int									newFd_;
2621 						deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2622 						NativeHandle						newFd	(newFd_);
2623 
2624 						TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2625 						TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2626 						TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2627 						TCU_CHECK(recvData == sendData);
2628 						TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2629 
2630 						{
2631 							const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2632 
2633 							if (transference == TRANSFERENCE_COPY)
2634 								VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2635 							else if (transference == TRANSFERENCE_REFERENCE)
2636 							{
2637 								submitDummySignal(vkd, queue, *newFence);
2638 								VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2639 							}
2640 							else
2641 								DE_FATAL("Unknown permanence.");
2642 
2643 							VK_CHECK(vkd.queueWaitIdle(queue));
2644 						}
2645 					}
2646 				}
2647 			}
2648 		}
2649 	}
2650 
2651 	return tcu::TestStatus::pass("Pass");
2652 #else
2653 	DE_UNREF(context);
2654 	DE_UNREF(config);
2655 	TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2656 #endif
2657 }
2658 
testBufferQueries(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)2659 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
2660 {
2661 	const vk::VkBufferCreateFlags		createFlags[]		=
2662 	{
2663 		0u,
2664 		vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2665 		vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2666 		vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2667 	};
2668 	const vk::VkBufferUsageFlags		usageFlags[]		=
2669 	{
2670 		vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2671 		vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2672 		vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2673 		vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2674 		vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2675 		vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2676 		vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2677 		vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2678 		vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2679 	};
2680 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2681 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, externalType, 0u));
2682 	const vk::InstanceDriver			vki					(vkp, *instance);
2683 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2684 	const vk::VkPhysicalDeviceFeatures	deviceFeatures		(vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2685 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2686 
2687 	// VkDevice is only created if physical device claims to support any of these types.
2688 	vk::Move<vk::VkDevice>				device;
2689 	de::MovePtr<vk::DeviceDriver>		vkd;
2690 	bool								deviceHasDedicated	= false;
2691 
2692 	TestLog&							log					= context.getTestContext().getLog();
2693 
2694 	for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2695 	for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2696 	{
2697 		const vk::VkBufferViewCreateFlags				createFlag		= createFlags[createFlagNdx];
2698 		const vk::VkBufferUsageFlags					usageFlag		= usageFlags[usageFlagNdx];
2699 		const vk::VkPhysicalDeviceExternalBufferInfo	info			=
2700 		{
2701 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
2702 			DE_NULL,
2703 			createFlag,
2704 			usageFlag,
2705 			externalType
2706 		};
2707 		vk::VkExternalBufferProperties					properties		=
2708 		{
2709 			vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
2710 			DE_NULL,
2711 			{ 0u, 0u, 0u }
2712 		};
2713 
2714 		if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2715 			(deviceFeatures.sparseBinding == VK_FALSE))
2716 			continue;
2717 
2718 		if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2719 			(deviceFeatures.sparseResidencyAliased == VK_FALSE))
2720 			continue;
2721 
2722 		if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2723 			(deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2724 			continue;
2725 
2726 		vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
2727 
2728 		log << TestLog::Message << properties << TestLog::EndMessage;
2729 
2730 		TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
2731 		TCU_CHECK(properties.pNext == DE_NULL);
2732 		// \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2733 
2734 		if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
2735 		{
2736 			const bool	requiresDedicated	= (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2737 
2738 			if (!device || (requiresDedicated && !deviceHasDedicated))
2739 			{
2740 				// \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2741 				try
2742 				{
2743 					device				= createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2744 					vkd					= de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, *instance, *device));
2745 					deviceHasDedicated	= requiresDedicated;
2746 				}
2747 				catch (const tcu::NotSupportedError& e)
2748 				{
2749 					log << e;
2750 					TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2751 				}
2752 			}
2753 		}
2754 
2755 		if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
2756 		{
2757 			DE_ASSERT(!!device);
2758 			DE_ASSERT(vkd);
2759 
2760 			if (deviceHasDedicated)
2761 			{
2762 				const vk::Unique<vk::VkBuffer>				buffer						(createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2763 				const vk::VkMemoryDedicatedRequirements		reqs						(getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2764 				const bool									propertiesRequiresDedicated	= (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2765 				const bool									objectRequiresDedicated		= (reqs.requiresDedicatedAllocation != VK_FALSE);
2766 
2767 				if (propertiesRequiresDedicated != objectRequiresDedicated)
2768 					TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2769 			}
2770 			else
2771 			{
2772 				// We can't query whether dedicated memory is required or not on per-object basis.
2773 				// This check should be redundant as the code above tries to create device with
2774 				// VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2775 				// is required. However, checking again doesn't hurt.
2776 				TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
2777 			}
2778 		}
2779 	}
2780 
2781 	return tcu::TestStatus::pass("Pass");
2782 }
2783 
2784 struct MemoryTestConfig
2785 {
MemoryTestConfigvkt::api::__anon041f48660111::MemoryTestConfig2786 												MemoryTestConfig	(vk::VkExternalMemoryHandleTypeFlagBits	externalType_,
2787 																	 bool										hostVisible_,
2788 																	 bool										dedicated_)
2789 		: externalType	(externalType_)
2790 		, hostVisible	(hostVisible_)
2791 		, dedicated		(dedicated_)
2792 	{
2793 	}
2794 
2795 	vk::VkExternalMemoryHandleTypeFlagBits	externalType;
2796 	bool									hostVisible;
2797 	bool									dedicated;
2798 };
2799 
2800 #if (DE_OS == DE_OS_WIN32)
chooseMemoryType(deUint32 bits)2801 deUint32 chooseMemoryType (deUint32 bits)
2802 {
2803 	if (bits == 0)
2804 		TCU_THROW(NotSupportedError, "No compatible memory type found");
2805 
2806 	return deCtz32(bits);
2807 }
2808 #endif
2809 
testMemoryWin32Create(Context & context,MemoryTestConfig config)2810 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2811 {
2812 #if (DE_OS == DE_OS_WIN32)
2813 	const vk::PlatformInterface&				vkp					(context.getPlatformInterface());
2814 	const vk::Unique<vk::VkInstance>			instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
2815 	const vk::InstanceDriver					vki					(vkp, *instance);
2816 	const vk::VkPhysicalDevice					physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2817 	const deUint32								queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2818 	const vk::Unique<vk::VkDevice>				device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2819 	const vk::DeviceDriver						vkd					(vkp, *instance, *device);
2820 	const vk::VkBufferUsageFlags				usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2821 	const deUint32								seed				= 1261033864u;
2822 	const vk::VkDeviceSize						bufferSize			= 1024;
2823 	const std::vector<deUint8>					testData			(genTestData(seed, (size_t)bufferSize));
2824 
2825 	const vk::VkPhysicalDeviceMemoryProperties	memoryProps			= vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2826 	const deUint32								compatibleMemTypes	= vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2827 
2828 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2829 
2830 	// \note Buffer is only allocated to get memory requirements
2831 	deUint32									exportedMemoryTypeIndex	= ~0U;
2832 	const vk::Unique<vk::VkBuffer>				buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2833 	const vk::VkMemoryRequirements				requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
2834 	const vk::VkExportMemoryWin32HandleInfoKHR	win32Info				=
2835 	{
2836 		vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2837 		DE_NULL,
2838 
2839 		(vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2840 		DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2841 		DE_NULL
2842 	};
2843 	const vk::VkExportMemoryAllocateInfo		exportInfo			=
2844 	{
2845 		vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
2846 		&win32Info,
2847 		(vk::VkExternalMemoryHandleTypeFlags)config.externalType
2848 	};
2849 
2850 	exportedMemoryTypeIndex = chooseMemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2851 	const vk::VkMemoryAllocateInfo				info				=
2852 	{
2853 		vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2854 		&exportInfo,
2855 		requirements.size,
2856 		exportedMemoryTypeIndex
2857 	};
2858 	const vk::Unique<vk::VkDeviceMemory>		memory				(vk::allocateMemory(vkd, *device, &info));
2859 	NativeHandle								handleA;
2860 
2861 	if (config.hostVisible)
2862 		writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2863 
2864 	getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2865 
2866 	{
2867 		const vk::Unique<vk::VkDeviceMemory>	memoryA	(importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2868 
2869 		if (config.hostVisible)
2870 		{
2871 			const std::vector<deUint8>		testDataA		(genTestData(seed ^ 124798807u, (size_t)bufferSize));
2872 			const std::vector<deUint8>		testDataB		(genTestData(seed ^ 970834278u, (size_t)bufferSize));
2873 
2874 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2875 			checkHostMemory(vkd, *device, *memory,  testData.size(), &testData[0]);
2876 
2877 			writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2878 			writeHostMemory(vkd, *device, *memory,  testDataA.size(), &testDataB[0]);
2879 
2880 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2881 			checkHostMemory(vkd, *device, *memory,  testData.size(), &testDataB[0]);
2882 		}
2883 	}
2884 
2885 	return tcu::TestStatus::pass("Pass");
2886 #else
2887 	DE_UNREF(context);
2888 	DE_UNREF(config);
2889 	TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2890 #endif
2891 }
2892 
testMemoryImportTwice(Context & context,MemoryTestConfig config)2893 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2894 {
2895 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
2896 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
2897 	const vk::InstanceDriver				vki					(vkp, *instance);
2898 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2899 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2900 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2901 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
2902 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2903 	const deUint32							seed				= 1261033864u;
2904 	const vk::VkDeviceSize					bufferSize			= 1024;
2905 	const std::vector<deUint8>				testData			(genTestData(seed, (size_t)bufferSize));
2906 
2907 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2908 
2909 	deUint32								exportedMemoryTypeIndex	= ~0U;
2910 	// \note Buffer is only allocated to get memory requirements
2911 	const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2912 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
2913 	const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2914 	NativeHandle							handleA;
2915 
2916 	if (config.hostVisible)
2917 		writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2918 
2919 	getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2920 
2921 	{
2922 		const vk::Unique<vk::VkBuffer>			bufferA	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2923 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2924 		NativeHandle							handleB	(handleA);
2925 		const vk::Unique<vk::VkDeviceMemory>	memoryA	(config.dedicated
2926 														 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
2927 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2928 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
2929 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
2930 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2931 
2932 		if (config.hostVisible)
2933 		{
2934 			const std::vector<deUint8>		testDataA		(genTestData(seed ^ 124798807u, (size_t)bufferSize));
2935 			const std::vector<deUint8>		testDataB		(genTestData(seed ^ 970834278u, (size_t)bufferSize));
2936 
2937 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2938 			checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
2939 
2940 			writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
2941 			writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
2942 
2943 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2944 			checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2945 		}
2946 	}
2947 
2948 	return tcu::TestStatus::pass("Pass");
2949 }
2950 
testMemoryMultimpleImports(Context & context,MemoryTestConfig config)2951 tcu::TestStatus testMemoryMultimpleImports (Context& context, MemoryTestConfig config)
2952 {
2953 	const size_t							count				= 4 * 1024;
2954 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
2955 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
2956 	const vk::InstanceDriver				vki					(vkp, *instance);
2957 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2958 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2959 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2960 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
2961 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2962 	const vk::VkDeviceSize					bufferSize			= 1024;
2963 
2964 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2965 
2966 	deUint32								exportedMemoryTypeIndex	= ~0U;
2967 	// \note Buffer is only allocated to get memory requirements
2968 	const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2969 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
2970 	const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
2971 	NativeHandle							handleA;
2972 
2973 	getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2974 
2975 	for (size_t ndx = 0; ndx < count; ndx++)
2976 	{
2977 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2978 		NativeHandle							handleB	(handleA);
2979 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
2980 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
2981 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2982 	}
2983 
2984 	return tcu::TestStatus::pass("Pass");
2985 }
2986 
testMemoryMultimpleExports(Context & context,MemoryTestConfig config)2987 tcu::TestStatus testMemoryMultimpleExports (Context& context, MemoryTestConfig config)
2988 {
2989 	const size_t							count				= 4 * 1024;
2990 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
2991 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
2992 	const vk::InstanceDriver				vki					(vkp, *instance);
2993 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
2994 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2995 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2996 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
2997 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2998 	const vk::VkDeviceSize					bufferSize			= 1024;
2999 
3000 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3001 
3002 	deUint32								exportedMemoryTypeIndex	= ~0U;
3003 	// \note Buffer is only allocated to get memory requirements
3004 	const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3005 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3006 	const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3007 
3008 	for (size_t ndx = 0; ndx < count; ndx++)
3009 	{
3010 		NativeHandle	handle;
3011 		getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3012 	}
3013 
3014 	return tcu::TestStatus::pass("Pass");
3015 }
3016 
testMemoryFdDup(Context & context,MemoryTestConfig config)3017 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3018 {
3019 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3020 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3021 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3022 	const vk::InstanceDriver			vki					(vkp, *instance);
3023 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3024 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3025 
3026 	{
3027 		const vk::Unique<vk::VkDevice>			device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3028 		const vk::DeviceDriver					vkd				(vkp, *instance, *device);
3029 
3030 		TestLog&								log				= context.getTestContext().getLog();
3031 		const vk::VkBufferUsageFlags			usage			= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3032 		const vk::VkDeviceSize					bufferSize		= 1024;
3033 		const deUint32							seed			= 851493858u;
3034 		const std::vector<deUint8>				testData		(genTestData(seed, (size_t)bufferSize));
3035 
3036 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3037 
3038 		deUint32								exportedMemoryTypeIndex	= ~0U;
3039 		// \note Buffer is only allocated to get memory requirements
3040 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3041 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3042 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3043 
3044 		if (config.hostVisible)
3045 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3046 
3047 		const NativeHandle						fd				(getMemoryFd(vkd, *device, *memory, config.externalType));
3048 		NativeHandle							newFd			(dup(fd.getFd()));
3049 
3050 		if (newFd.getFd() < 0)
3051 			log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3052 
3053 		TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3054 
3055 		{
3056 			const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3057 			const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3058 																 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3059 																 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3060 
3061 			if (config.hostVisible)
3062 			{
3063 				const std::vector<deUint8>	testDataA	(genTestData(seed ^ 672929437u, (size_t)bufferSize));
3064 
3065 				checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3066 
3067 				writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3068 				checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3069 			}
3070 		}
3071 
3072 		return tcu::TestStatus::pass("Pass");
3073 	}
3074 #else
3075 	DE_UNREF(context);
3076 	DE_UNREF(config);
3077 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3078 #endif
3079 }
3080 
testMemoryFdDup2(Context & context,MemoryTestConfig config)3081 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3082 {
3083 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3084 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3085 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3086 	const vk::InstanceDriver			vki					(vkp, *instance);
3087 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3088 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3089 
3090 	{
3091 		const vk::Unique<vk::VkDevice>			device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3092 		const vk::DeviceDriver					vkd				(vkp, *instance, *device);
3093 
3094 		TestLog&								log				= context.getTestContext().getLog();
3095 		const vk::VkBufferUsageFlags			usage			= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3096 		const vk::VkDeviceSize					bufferSize		= 1024;
3097 		const deUint32							seed			= 224466865u;
3098 		const std::vector<deUint8>				testData		(genTestData(seed, (size_t)bufferSize));
3099 
3100 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3101 
3102 		deUint32								exportedMemoryTypeIndex	= ~0U;
3103 		// \note Buffer is only allocated to get memory requirements
3104 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3105 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3106 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3107 
3108 		if (config.hostVisible)
3109 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3110 
3111 		const NativeHandle						fd				(getMemoryFd(vkd, *device, *memory, config.externalType));
3112 		NativeHandle							secondFd		(getMemoryFd(vkd, *device, *memory, config.externalType));
3113 		const int								newFd			(dup2(fd.getFd(), secondFd.getFd()));
3114 
3115 		if (newFd < 0)
3116 			log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3117 
3118 		TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3119 
3120 		{
3121 			const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3122 			const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3123 																 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3124 																 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3125 
3126 			if (config.hostVisible)
3127 			{
3128 				const std::vector<deUint8>	testDataA	(genTestData(seed ^ 99012346u, (size_t)bufferSize));
3129 
3130 				checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3131 
3132 				writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3133 				checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3134 			}
3135 		}
3136 
3137 		return tcu::TestStatus::pass("Pass");
3138 	}
3139 #else
3140 	DE_UNREF(context);
3141 	DE_UNREF(config);
3142 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3143 #endif
3144 }
3145 
testMemoryFdDup3(Context & context,MemoryTestConfig config)3146 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3147 {
3148 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3149 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3150 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3151 	const vk::InstanceDriver			vki					(vkp, *instance);
3152 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3153 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3154 
3155 	{
3156 		const vk::Unique<vk::VkDevice>			device			(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3157 		const vk::DeviceDriver					vkd				(vkp, *instance, *device);
3158 
3159 		TestLog&								log				= context.getTestContext().getLog();
3160 		const vk::VkBufferUsageFlags			usage			= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3161 		const vk::VkDeviceSize					bufferSize		= 1024;
3162 		const deUint32							seed			= 2554088961u;
3163 		const std::vector<deUint8>				testData		(genTestData(seed, (size_t)bufferSize));
3164 
3165 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3166 
3167 		deUint32								exportedMemoryTypeIndex	= ~0U;
3168 		// \note Buffer is only allocated to get memory requirements
3169 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3170 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3171 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3172 
3173 		if (config.hostVisible)
3174 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3175 
3176 		const NativeHandle						fd				(getMemoryFd(vkd, *device, *memory, config.externalType));
3177 		NativeHandle							secondFd		(getMemoryFd(vkd, *device, *memory, config.externalType));
3178 		const int								newFd			(dup3(fd.getFd(), secondFd.getFd(), 0));
3179 
3180 		if (newFd < 0)
3181 			log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3182 
3183 		TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3184 
3185 		{
3186 			const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3187 			const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3188 																 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3189 																 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3190 
3191 			if (config.hostVisible)
3192 			{
3193 				const std::vector<deUint8>	testDataA	(genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3194 
3195 				checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3196 
3197 				writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3198 				checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3199 			}
3200 		}
3201 
3202 		return tcu::TestStatus::pass("Pass");
3203 	}
3204 #else
3205 	DE_UNREF(context);
3206 	DE_UNREF(config);
3207 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3208 #endif
3209 }
3210 
testMemoryFdSendOverSocket(Context & context,MemoryTestConfig config)3211 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3212 {
3213 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3214 	const vk::PlatformInterface&				vkp					(context.getPlatformInterface());
3215 	const vk::Unique<vk::VkInstance>			instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3216 	const vk::InstanceDriver					vki					(vkp, *instance);
3217 	const vk::VkPhysicalDevice					physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3218 	const deUint32								queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3219 
3220 	{
3221 		const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3222 		const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3223 
3224 		TestLog&								log					= context.getTestContext().getLog();
3225 		const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3226 		const vk::VkDeviceSize					bufferSize			= 1024;
3227 		const deUint32							seed				= 3403586456u;
3228 		const std::vector<deUint8>				testData			(genTestData(seed, (size_t)bufferSize));
3229 
3230 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3231 
3232 		deUint32								exportedMemoryTypeIndex	= ~0U;
3233 		// \note Buffer is only allocated to get memory requirements
3234 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3235 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3236 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vki, physicalDevice, vkd, *device, requirements, config.externalType, config.hostVisible, config.dedicated ? *buffer : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3237 
3238 		if (config.hostVisible)
3239 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3240 
3241 		const NativeHandle						fd					(getMemoryFd(vkd, *device, *memory, config.externalType));
3242 
3243 		{
3244 			int sv[2];
3245 
3246 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3247 			{
3248 				log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3249 				TCU_FAIL("Failed to create socket pair");
3250 			}
3251 
3252 			{
3253 				const NativeHandle	srcSocket	(sv[0]);
3254 				const NativeHandle	dstSocket	(sv[1]);
3255 				std::string			sendData	("deqp");
3256 
3257 				// Send FD
3258 				{
3259 					const int			fdRaw	(fd.getFd());
3260 					msghdr				msg;
3261 					cmsghdr*			cmsg;
3262 					char				tmpBuffer[CMSG_SPACE(sizeof(int))];
3263 					iovec				iov		= { &sendData[0], sendData.length()};
3264 
3265 					deMemset(&msg, 0, sizeof(msg));
3266 
3267 					msg.msg_control		= tmpBuffer;
3268 					msg.msg_controllen	= sizeof(tmpBuffer);
3269 					msg.msg_iovlen		= 1;
3270 					msg.msg_iov			= &iov;
3271 
3272 					cmsg				= CMSG_FIRSTHDR(&msg);
3273 					cmsg->cmsg_level	= SOL_SOCKET;
3274 					cmsg->cmsg_type		= SCM_RIGHTS;
3275 					cmsg->cmsg_len		= CMSG_LEN(sizeof(int));
3276 
3277 					deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3278 					msg.msg_controllen = cmsg->cmsg_len;
3279 
3280 					if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3281 					{
3282 						log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3283 						TCU_FAIL("Failed to send fd over socket");
3284 					}
3285 				}
3286 
3287 				// Recv FD
3288 				{
3289 					msghdr			msg;
3290 					char			tmpBuffer[CMSG_SPACE(sizeof(int))];
3291 					std::string		recvData	(4, '\0');
3292 					iovec			iov			= { &recvData[0], recvData.length() };
3293 
3294 					deMemset(&msg, 0, sizeof(msg));
3295 
3296 					msg.msg_control		= tmpBuffer;
3297 					msg.msg_controllen	= sizeof(tmpBuffer);
3298 					msg.msg_iovlen		= 1;
3299 					msg.msg_iov			= &iov;
3300 
3301 					const ssize_t	bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3302 
3303 					if (bytes < 0)
3304 					{
3305 						log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3306 						TCU_FAIL("Failed to recv fd over socket");
3307 
3308 					}
3309 					else if (bytes != (ssize_t)sendData.length())
3310 					{
3311 						TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3312 					}
3313 					else
3314 					{
3315 						const cmsghdr* const	cmsg	= CMSG_FIRSTHDR(&msg);
3316 						int						newFd_;
3317 						deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3318 						NativeHandle			newFd	(newFd_);
3319 
3320 						TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3321 						TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3322 						TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3323 						TCU_CHECK(recvData == sendData);
3324 						TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3325 
3326 						{
3327 							const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3328 							const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3329 																				 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3330 																				 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3331 
3332 							if (config.hostVisible)
3333 							{
3334 								const std::vector<deUint8>	testDataA	(genTestData(seed ^ 23478978u, (size_t)bufferSize));
3335 
3336 								checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3337 
3338 								writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3339 								checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3340 							}
3341 						}
3342 					}
3343 				}
3344 			}
3345 		}
3346 	}
3347 
3348 	return tcu::TestStatus::pass("Pass");
3349 #else
3350 	DE_UNREF(context);
3351 	DE_UNREF(config);
3352 	TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3353 #endif
3354 }
3355 
3356 struct BufferTestConfig
3357 {
BufferTestConfigvkt::api::__anon041f48660111::BufferTestConfig3358 											BufferTestConfig	(vk::VkExternalMemoryHandleTypeFlagBits		externalType_,
3359 																 bool										dedicated_)
3360 		: externalType	(externalType_)
3361 		, dedicated		(dedicated_)
3362 	{
3363 	}
3364 
3365 	vk::VkExternalMemoryHandleTypeFlagBits	externalType;
3366 	bool									dedicated;
3367 };
3368 
testBufferBindExportImportBind(Context & context,const BufferTestConfig config)3369 tcu::TestStatus testBufferBindExportImportBind (Context&				context,
3370 												const BufferTestConfig	config)
3371 {
3372 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3373 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3374 	const vk::InstanceDriver				vki					(vkp, *instance);
3375 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3376 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3377 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3378 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3379 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3380 	const vk::VkDeviceSize					bufferSize			= 1024;
3381 
3382 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3383 
3384 	deUint32								exportedMemoryTypeIndex	= ~0U;
3385 	// \note Buffer is only allocated to get memory requirements
3386 	const vk::Unique<vk::VkBuffer>			bufferA					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3387 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *bufferA));
3388 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3389 	NativeHandle							handle;
3390 
3391 	VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3392 
3393 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3394 
3395 	{
3396 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3397 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3398 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3399 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3400 
3401 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3402 	}
3403 
3404 	return tcu::TestStatus::pass("Pass");
3405 }
3406 
testBufferExportBindImportBind(Context & context,const BufferTestConfig config)3407 tcu::TestStatus testBufferExportBindImportBind (Context&				context,
3408 												const BufferTestConfig	config)
3409 {
3410 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3411 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3412 	const vk::InstanceDriver				vki					(vkp, *instance);
3413 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3414 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3415 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3416 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3417 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3418 	const vk::VkDeviceSize					bufferSize			= 1024;
3419 
3420 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3421 
3422 	deUint32								exportedMemoryTypeIndex	= ~0U;
3423 	// \note Buffer is only allocated to get memory requirements
3424 	const vk::Unique<vk::VkBuffer>			bufferA					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3425 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *bufferA));
3426 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3427 	NativeHandle							handle;
3428 
3429 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3430 	VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3431 
3432 	{
3433 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3434 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3435 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3436 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3437 
3438 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3439 	}
3440 
3441 	return tcu::TestStatus::pass("Pass");
3442 }
3443 
testBufferExportImportBindBind(Context & context,const BufferTestConfig config)3444 tcu::TestStatus testBufferExportImportBindBind (Context&				context,
3445 												const BufferTestConfig	config)
3446 {
3447 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3448 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3449 	const vk::InstanceDriver				vki					(vkp, *instance);
3450 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3451 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3452 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3453 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3454 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3455 	const vk::VkDeviceSize					bufferSize			= 1024;
3456 
3457 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3458 
3459 	deUint32								exportedMemoryTypeIndex	= ~0U;
3460 	// \note Buffer is only allocated to get memory requirements
3461 	const vk::Unique<vk::VkBuffer>			bufferA					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3462 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *bufferA));
3463 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0, exportedMemoryTypeIndex));
3464 	NativeHandle							handle;
3465 
3466 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3467 
3468 	{
3469 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3470 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3471 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3472 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3473 
3474 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3475 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3476 	}
3477 
3478 	return tcu::TestStatus::pass("Pass");
3479 }
3480 
testImageQueries(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)3481 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3482 {
3483 	const vk::VkImageCreateFlags		createFlags[]		=
3484 	{
3485 		0u,
3486 		vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3487 		vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3488 		vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3489 		vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3490 		vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3491 	};
3492 	const vk::VkImageUsageFlags			usageFlags[]		=
3493 	{
3494 		vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3495 		vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3496 		vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3497 		vk::VK_IMAGE_USAGE_STORAGE_BIT,
3498 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3499 		vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3500 		vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
3501 		vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3502 	};
3503 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3504 	const vk::Unique<vk::VkInstance>	instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, externalType, 0u));
3505 	const vk::InstanceDriver			vki					(vkp, *instance);
3506 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3507 	const vk::VkPhysicalDeviceFeatures	deviceFeatures		(vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3508 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3509 
3510 	// VkDevice is only created if physical device claims to support any of these types.
3511 	vk::Move<vk::VkDevice>				device;
3512 	de::MovePtr<vk::DeviceDriver>		vkd;
3513 	bool								deviceHasDedicated	= false;
3514 
3515 	TestLog&							log					= context.getTestContext().getLog();
3516 
3517 	for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3518 	for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3519 	{
3520 		const vk::VkImageViewCreateFlags						createFlag		= createFlags[createFlagNdx];
3521 		const vk::VkImageUsageFlags								usageFlag		= usageFlags[usageFlagNdx];
3522 		const vk::VkFormat										format			= vk::VK_FORMAT_R8G8B8A8_UNORM;
3523 		const vk::VkImageType									type			= vk::VK_IMAGE_TYPE_2D;
3524 		const vk::VkImageTiling									tiling			= vk::VK_IMAGE_TILING_OPTIMAL;
3525 		const vk::VkPhysicalDeviceExternalImageFormatInfo		externalInfo	=
3526 		{
3527 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3528 			DE_NULL,
3529 			externalType
3530 		};
3531 		const vk::VkPhysicalDeviceImageFormatInfo2				info			=
3532 		{
3533 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3534 			&externalInfo,
3535 
3536 			format,
3537 			type,
3538 			tiling,
3539 			usageFlag,
3540 			createFlag,
3541 		};
3542 		vk::VkExternalImageFormatProperties						externalProperties	=
3543 		{
3544 			vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3545 			DE_NULL,
3546 			{ 0u, 0u, 0u }
3547 		};
3548 		vk::VkImageFormatProperties2							properties			=
3549 		{
3550 			vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3551 			&externalProperties,
3552 			{
3553 				{ 0u, 0u, 0u },
3554 				0u,
3555 				0u,
3556 				0u,
3557 				0u
3558 			}
3559 		};
3560 
3561 		if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3562 			(deviceFeatures.sparseBinding == VK_FALSE))
3563 			continue;
3564 
3565 		if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3566 			(deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3567 			continue;
3568 
3569 		if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3570 			(deviceFeatures.sparseResidencyAliased == VK_FALSE))
3571 			continue;
3572 
3573 		vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties);
3574 
3575 		log << TestLog::Message << externalProperties << TestLog::EndMessage;
3576 		TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
3577 		TCU_CHECK(externalProperties.pNext == DE_NULL);
3578 		// \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3579 
3580 		if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3581 		{
3582 			const bool	requiresDedicated	= (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3583 
3584 			if (!device || (requiresDedicated && !deviceHasDedicated))
3585 			{
3586 				// \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3587 				try
3588 				{
3589 					device				= createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3590 					vkd					= de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, *instance, *device));
3591 					deviceHasDedicated	= requiresDedicated;
3592 				}
3593 				catch (const tcu::NotSupportedError& e)
3594 				{
3595 					log << e;
3596 					TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3597 				}
3598 			}
3599 		}
3600 
3601 		if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3602 		{
3603 			DE_ASSERT(!!device);
3604 			DE_ASSERT(vkd);
3605 
3606 			if (deviceHasDedicated)
3607 			{
3608 				const vk::Unique<vk::VkImage>				image						(createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3609 				const vk::VkMemoryDedicatedRequirements		reqs						(getMemoryDedicatedRequirements(*vkd, *device, *image));
3610 				const bool									propertiesRequiresDedicated	= (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3611 				const bool									objectRequiresDedicated		= (reqs.requiresDedicatedAllocation != VK_FALSE);
3612 
3613 				if (propertiesRequiresDedicated != objectRequiresDedicated)
3614 					TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3615 			}
3616 			else
3617 			{
3618 				// We can't query whether dedicated memory is required or not on per-object basis.
3619 				// This check should be redundant as the code above tries to create device with
3620 				// VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3621 				// is required. However, checking again doesn't hurt.
3622 				TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3623 			}
3624 		}
3625 	}
3626 
3627 	return tcu::TestStatus::pass("Pass");
3628 }
3629 
3630 struct ImageTestConfig
3631 {
ImageTestConfigvkt::api::__anon041f48660111::ImageTestConfig3632 											ImageTestConfig	(vk::VkExternalMemoryHandleTypeFlagBits		externalType_,
3633 															 bool										dedicated_)
3634 		: externalType	(externalType_)
3635 		, dedicated		(dedicated_)
3636 	{
3637 	}
3638 
3639 	vk::VkExternalMemoryHandleTypeFlagBits	externalType;
3640 	bool									dedicated;
3641 };
3642 
testImageBindExportImportBind(Context & context,const ImageTestConfig config)3643 tcu::TestStatus testImageBindExportImportBind (Context&					context,
3644 											   const ImageTestConfig	config)
3645 {
3646 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3647 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3648 	const vk::InstanceDriver				vki					(vkp, *instance);
3649 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3650 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3651 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3652 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3653 	const vk::VkImageUsageFlags				usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3654 	const vk::VkFormat						format				= vk::VK_FORMAT_R8G8B8A8_UNORM;
3655 	const deUint32							width				= 64u;
3656 	const deUint32							height				= 64u;
3657 	const vk::VkImageTiling					tiling				= vk::VK_IMAGE_TILING_OPTIMAL;
3658 
3659 	checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3660 
3661 	deUint32								exportedMemoryTypeIndex	= ~0U;
3662 	const vk::Unique<vk::VkImage>			imageA					(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3663 	const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *imageA));
3664 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3665 	NativeHandle							handle;
3666 
3667 	VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3668 
3669 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3670 
3671 	{
3672 		const vk::Unique<vk::VkImage>			imageB	(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3673 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3674 														 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3675 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3676 
3677 		VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3678 	}
3679 
3680 	return tcu::TestStatus::pass("Pass");
3681 }
3682 
testImageExportBindImportBind(Context & context,const ImageTestConfig config)3683 tcu::TestStatus testImageExportBindImportBind (Context&					context,
3684 											   const ImageTestConfig	config)
3685 {
3686 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3687 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3688 	const vk::InstanceDriver				vki					(vkp, *instance);
3689 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3690 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3691 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3692 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3693 	const vk::VkImageUsageFlags				usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3694 	const vk::VkFormat						format				= vk::VK_FORMAT_R8G8B8A8_UNORM;
3695 	const deUint32							width				= 64u;
3696 	const deUint32							height				= 64u;
3697 	const vk::VkImageTiling					tiling				= vk::VK_IMAGE_TILING_OPTIMAL;
3698 
3699 	checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3700 
3701 	deUint32								exportedMemoryTypeIndex	= ~0U;
3702 	const vk::Unique<vk::VkImage>			imageA					(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3703 	const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *imageA));
3704 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3705 	NativeHandle							handle;
3706 
3707 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3708 	VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3709 
3710 	{
3711 		const vk::Unique<vk::VkImage>			imageB	(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3712 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3713 														 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3714 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3715 
3716 		VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3717 	}
3718 
3719 	return tcu::TestStatus::pass("Pass");
3720 }
3721 
testImageExportImportBindBind(Context & context,const ImageTestConfig config)3722 tcu::TestStatus testImageExportImportBindBind (Context&					context,
3723 											   const ImageTestConfig	config)
3724 {
3725 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3726 	const vk::Unique<vk::VkInstance>		instance			(createInstance(vkp, context.getUsedApiVersion(), 0u, config.externalType, 0u));
3727 	const vk::InstanceDriver				vki					(vkp, *instance);
3728 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3729 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3730 	const vk::Unique<vk::VkDevice>			device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3731 	const vk::DeviceDriver					vkd					(vkp, *instance, *device);
3732 	const vk::VkImageUsageFlags				usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3733 	const vk::VkFormat						format				= vk::VK_FORMAT_R8G8B8A8_UNORM;
3734 	const deUint32							width				= 64u;
3735 	const deUint32							height				= 64u;
3736 	const vk::VkImageTiling					tiling				= vk::VK_IMAGE_TILING_OPTIMAL;
3737 
3738 	checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3739 
3740 	deUint32								exportedMemoryTypeIndex	= ~0U;
3741 	// \note Image is only allocated to get memory requirements
3742 	const vk::Unique<vk::VkImage>			imageA					(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3743 	const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *imageA));
3744 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0, exportedMemoryTypeIndex));
3745 	NativeHandle							handle;
3746 
3747 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3748 
3749 	{
3750 		const vk::Unique<vk::VkImage>			imageB	(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3751 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3752 														 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3753 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3754 
3755 		VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3756 		VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3757 	}
3758 
3759 	return tcu::TestStatus::pass("Pass");
3760 }
createFenceTests(tcu::TestContext & testCtx,vk::VkExternalFenceHandleTypeFlagBits externalType)3761 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
3762 {
3763 	const struct
3764 	{
3765 		const char* const	name;
3766 		const Permanence	permanence;
3767 	} permanences[] =
3768 	{
3769 		{ "temporary", PERMANENCE_TEMPORARY	},
3770 		{ "permanent", PERMANENCE_PERMANENT	}
3771 	};
3772 
3773 	de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3774 
3775 	addFunctionCase(fenceGroup.get(), "info",	"Test external fence queries.",	testFenceQueries,	externalType);
3776 
3777 	for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3778 	{
3779 		const Permanence		permanence		(permanences[permanenceNdx].permanence);
3780 		const char* const		permanenceName	(permanences[permanenceNdx].name);
3781 		const FenceTestConfig	config			(externalType, permanence);
3782 
3783 		if (!isSupportedPermanence(externalType, permanence))
3784 			continue;
3785 
3786 		if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3787 			|| externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3788 		{
3789 			addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName,	"Test creating fence with win32 properties.",	testFenceWin32Create,	config);
3790 		}
3791 
3792 		addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName,				"Test importing fence twice.",											testFenceImportTwice,				config);
3793 		addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName,					"Test importing again over previously imported fence.",					testFenceImportReimport,			config);
3794 		addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName,		"Test importing fence multiple times.",									testFenceMultipleImports,			config);
3795 		addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName,	"Test signaling, exporting, importing and waiting for the sempahore.",	testFenceSignalExportImportWait,	config);
3796 		addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName,				"Test signaling and importing the fence.",								testFenceSignalImport,				config);
3797 		addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName,						"Test resetting the fence.",											testFenceReset,						config);
3798 		addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName,				"Test fences transference.",											testFenceTransference,				config);
3799 
3800 		if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
3801 			|| externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
3802 		{
3803 			// \note Not supported on WIN32 handles
3804 			addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName,	"Test exporting fence multiple times.",		testFenceMultipleExports,	config);
3805 
3806 			addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName,						"Test calling dup() on exported fence.",	testFenceFdDup,				config);
3807 			addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName,					"Test calling dup2() on exported fence.",	testFenceFdDup2,			config);
3808 			addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName,					"Test calling dup3() on exported fence.",	testFenceFdDup3,			config);
3809 			addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName,		"Test sending fence fd over socket.",		testFenceFdSendOverSocket,	config);
3810 		}
3811 
3812 		if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3813 		{
3814 			addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName,			"Test signaling and then waiting for the the sepmahore.",			testFenceSignalWaitImport,			config);
3815 			addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName,	"Test exporting, signaling, importing and waiting for the fence.",	testFenceExportSignalImportWait,	config);
3816 			addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName,	"Test exporting, importing, signaling and waiting for the fence.",	testFenceExportImportSignalWait,	config);
3817 		}
3818 	}
3819 
3820 	return fenceGroup;
3821 }
3822 
ValidateAHardwareBuffer(vk::VkFormat format,deUint64 requiredAhbUsage,const vk::DeviceDriver & vkd,const vk::VkDevice & device,vk::VkImageCreateFlags createFlag,deUint32 layerCount,bool & enableMaxLayerTest)3823 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
3824 {
3825 	DE_UNREF(createFlag);
3826 
3827 	AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
3828 	if (!ahbApi)
3829 	{
3830 		TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
3831 	}
3832 
3833 #if (DE_OS == DE_OS_ANDROID)
3834 	// If CubeMap create flag is used and AHB doesn't support CubeMap return false.
3835 	if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
3836 		return false;
3837 #endif
3838 
3839 	vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
3840 	if (ahb.internal == DE_NULL)
3841 	{
3842 		enableMaxLayerTest = false;
3843 		// try again with layerCount '1'
3844 		ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
3845 		if (ahb.internal == DE_NULL)
3846 		{
3847 			return false;
3848 		}
3849 	}
3850 	NativeHandle nativeHandle(ahb);
3851 	vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
3852 	{
3853 		vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
3854 		DE_NULL,
3855 		vk::VK_FORMAT_UNDEFINED,
3856 		0u,
3857 		0u,
3858 		{ vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY },
3859 		vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
3860 		vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
3861 		vk::VK_CHROMA_LOCATION_COSITED_EVEN,
3862 		vk::VK_CHROMA_LOCATION_COSITED_EVEN
3863 	};
3864 	vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
3865 	{
3866 		vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
3867 		&formatProperties,
3868 		0u,
3869 		0u
3870 	};
3871 
3872 	VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
3873 	TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
3874 	TCU_CHECK(formatProperties.format == format);
3875 	TCU_CHECK(formatProperties.externalFormat != 0u);
3876 	TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
3877 	TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
3878 	return true;
3879 }
3880 
testAndroidHardwareBufferImageFormat(Context & context,vk::VkFormat format)3881 tcu::TestStatus testAndroidHardwareBufferImageFormat  (Context& context, vk::VkFormat format)
3882 {
3883 	AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
3884 	if (!ahbApi)
3885 	{
3886 		TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
3887 	}
3888 
3889 	const vk::VkExternalMemoryHandleTypeFlagBits  externalMemoryType  =	vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
3890 	const vk::PlatformInterface&				  vkp					(context.getPlatformInterface());
3891 	const vk::Unique<vk::VkInstance>			  instance				(createInstance(vkp, context.getUsedApiVersion(), externalMemoryType, 0u, 0u));
3892 	const vk::InstanceDriver					  vki					(vkp, *instance);
3893 	const vk::VkPhysicalDevice					  physicalDevice		(vk::chooseDevice(vki, *instance, context.getTestContext().getCommandLine()));
3894 	const deUint32								  queueFamilyIndex		(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3895 	const vk::Unique<vk::VkDevice>				  device				(createDevice(context.getUsedApiVersion(), vkp, *instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex));
3896 	const vk::DeviceDriver						  vkd					(vkp, *instance, *device);
3897 	TestLog&									  log				  = context.getTestContext().getLog();
3898 	const vk::VkPhysicalDeviceLimits			  limits			  = getPhysicalDeviceProperties(vki, physicalDevice).limits;
3899 
3900 	vk::VkPhysicalDeviceProtectedMemoryFeatures		protectedFeatures;
3901 	protectedFeatures.sType				= vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
3902 	protectedFeatures.pNext				= DE_NULL;
3903 	protectedFeatures.protectedMemory	= VK_FALSE;
3904 
3905 	vk::VkPhysicalDeviceFeatures2					deviceFeatures;
3906 	deviceFeatures.sType		= vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
3907 	deviceFeatures.pNext		= &protectedFeatures;
3908 
3909 	vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
3910 
3911 	const vk::VkImageUsageFlagBits				  usageFlags[]		  =
3912 	{
3913 		vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3914 		vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3915 		vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3916 		vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3917 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3918 	};
3919 	const vk::VkImageCreateFlagBits				  createFlags[]		  =
3920 	{
3921 		vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3922 		vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
3923 		vk::VK_IMAGE_CREATE_PROTECTED_BIT,
3924 		vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
3925 	};
3926 	const vk::VkImageTiling						  tilings[]			  =
3927 	{
3928 		vk::VK_IMAGE_TILING_OPTIMAL,
3929 		vk::VK_IMAGE_TILING_LINEAR,
3930 	};
3931 	deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
3932 	const size_t	numOfUsageFlags				= DE_LENGTH_OF_ARRAY(usageFlags);
3933 	const size_t	numOfCreateFlags			= DE_LENGTH_OF_ARRAY(createFlags);
3934 	const size_t	numOfFlagCombos				= 1u << (numOfUsageFlags + numOfCreateFlags);
3935 	const size_t	numOfTilings				= DE_LENGTH_OF_ARRAY(tilings);
3936 
3937 	for (size_t combo = 0; combo < numOfFlagCombos; combo++)
3938 	{
3939 		vk::VkImageUsageFlags	usage				= 0;
3940 		vk::VkImageCreateFlags	createFlag			= 0;
3941 		deUint64				requiredAhbUsage	= 0;
3942 		bool					enableMaxLayerTest	= true;
3943 		for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
3944 		{
3945 			if ((combo & (1u << usageNdx)) == 0)
3946 				continue;
3947 			usage |= usageFlags[usageNdx];
3948 			requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
3949 		}
3950 		for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
3951 		{
3952 			const size_t	bit	= numOfUsageFlags + createFlagNdx;
3953 			if ((combo & (1u << bit)) == 0)
3954 				continue;
3955 			if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
3956 				(protectedFeatures.protectedMemory == VK_FALSE))
3957 				continue;
3958 			createFlag |= createFlags[createFlagNdx];
3959 			requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
3960 		}
3961 
3962 		// Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
3963 		if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
3964 			continue;
3965 
3966 		// Only test a combination if AHardwareBuffer can be successfully allocated for it.
3967 		if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
3968 			continue;
3969 
3970 		bool foundAnyUsableTiling = false;
3971 		for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
3972 		{
3973 			const vk::VkImageTiling tiling = tilings[tilingIndex];
3974 
3975 			const vk::VkPhysicalDeviceExternalImageFormatInfo	externalInfo		=
3976 			{
3977 				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3978 				DE_NULL,
3979 				vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
3980 			};
3981 			const vk::VkPhysicalDeviceImageFormatInfo2			info				=
3982 			{
3983 				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3984 				&externalInfo,
3985 				format,
3986 				vk::VK_IMAGE_TYPE_2D,
3987 				tiling,
3988 				usage,
3989 				createFlag,
3990 			};
3991 
3992 			vk::VkAndroidHardwareBufferUsageANDROID				ahbUsageProperties	=
3993 			{
3994 				vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
3995 				DE_NULL,
3996 				0u
3997 			};
3998 			vk::VkExternalImageFormatProperties					externalProperties	=
3999 			{
4000 				vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4001 				&ahbUsageProperties,
4002 				{ 0u, 0u, 0u }
4003 			};
4004 			vk::VkImageFormatProperties2						properties			=
4005 			{
4006 				vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4007 				&externalProperties,
4008 				{
4009 					{ 0u, 0u, 0u },
4010 					0u,
4011 					0u,
4012 					0u,
4013 					0u
4014 				}
4015 			};
4016 
4017 			if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4018 			{
4019 				log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4020 				continue;
4021 			}
4022 
4023 			foundAnyUsableTiling = true;
4024 
4025 			TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4026 			TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4027 			TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4028 			deUint32 maxWidth   = properties.imageFormatProperties.maxExtent.width;
4029 			deUint32 maxHeight  = properties.imageFormatProperties.maxExtent.height;
4030 			TCU_CHECK(maxWidth >= 4096);
4031 			TCU_CHECK(maxHeight >= 4096);
4032 			// Even if not requested, at least one of GPU_* usage flags must be present.
4033 			TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4034 			// The AHB usage flags corresponding to the create and usage flags used in info must be present.
4035 			TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4036 
4037 			log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4038 				<< TestLog::EndMessage;
4039 
4040 			struct ImageSize
4041 			{
4042 				deUint32 width;
4043 				deUint32 height;
4044 			};
4045 			ImageSize sizes[] =
4046 			{
4047 				{64u, 64u},
4048 				{1024u, 2096u},
4049 			};
4050 			for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4051 			{
4052 				deUint32								exportedMemoryTypeIndex	= ~0U;
4053 				const vk::Unique<vk::VkImage>			image					(createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4054 				const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *image));
4055 				const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
4056 				NativeHandle							handle;
4057 
4058 				VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4059 				getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4060 
4061 				deUint32 ahbFormat = 0;
4062 				deUint64 anhUsage  = 0;
4063 				ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4064 				TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4065 				TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4066 
4067 				// Let watchdog know we're alive
4068 				context.getTestContext().touchWatchdog();
4069 			}
4070 
4071 			if (properties.imageFormatProperties.maxMipLevels > 1u)
4072 			{
4073 				deUint32								exportedMemoryTypeIndex	= ~0U;
4074 				const vk::Unique<vk::VkImage>			image					(createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, properties.imageFormatProperties.maxMipLevels));
4075 				const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *image));
4076 				const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
4077 				NativeHandle							handle;
4078 
4079 				VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4080 				getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4081 
4082 				deUint32 ahbFormat = 0;
4083 				deUint64 anhUsage  = 0;
4084 				ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4085 				TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4086 				TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4087 			}
4088 
4089 			if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4090 			{
4091 				deUint32								exportedMemoryTypeIndex	= ~0U;
4092 				const vk::Unique<vk::VkImage>			image					(createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4093 				const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *image));
4094 				const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements, externalMemoryType, *image, exportedMemoryTypeIndex));
4095 				NativeHandle							handle;
4096 
4097 				VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4098 				getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4099 
4100 				deUint32 ahbFormat = 0;
4101 				deUint64 anhUsage  = 0;
4102 				ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4103 				TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4104 				TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4105 			}
4106 		}
4107 
4108 		TCU_CHECK(foundAnyUsableTiling);
4109 	}
4110 	return tcu::TestStatus::pass("Pass");
4111 }
4112 
createFenceTests(tcu::TestContext & testCtx)4113 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4114 {
4115 	de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4116 
4117 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4118 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4119 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4120 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4121 
4122 	return fenceGroup;
4123 }
4124 
createSemaphoreTests(tcu::TestContext & testCtx,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)4125 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4126 {
4127 	const struct
4128 	{
4129 		const char* const	name;
4130 		const Permanence	permanence;
4131 	} permanences[] =
4132 	{
4133 		{ "temporary", PERMANENCE_TEMPORARY	},
4134 		{ "permanent", PERMANENCE_PERMANENT	}
4135 	};
4136 
4137 	de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4138 
4139 	addFunctionCase(semaphoreGroup.get(), "info",	"Test external semaphore queries.",	testSemaphoreQueries,	externalType);
4140 
4141 	for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4142 	{
4143 		const Permanence			permanence		(permanences[permanenceNdx].permanence);
4144 		const char* const			permanenceName	(permanences[permanenceNdx].name);
4145 		const SemaphoreTestConfig	config			(externalType, permanence);
4146 
4147 		if (!isSupportedPermanence(externalType, permanence))
4148 			continue;
4149 
4150 		if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4151 			|| externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4152 		{
4153 			addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,	"Test creating semaphore with win32 properties.",	testSemaphoreWin32Create,	config);
4154 		}
4155 
4156 		addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName,				"Test importing semaphore twice.",										testSemaphoreImportTwice,				config);
4157 		addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName,					"Test importing again over previously imported semaphore.",				testSemaphoreImportReimport,			config);
4158 		addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,		"Test importing semaphore multiple times.",								testSemaphoreMultipleImports,			config);
4159 		addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,	"Test signaling, exporting, importing and waiting for the sempahore.",	testSemaphoreSignalExportImportWait,	config);
4160 		addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName,				"Test signaling and importing the semaphore.",							testSemaphoreSignalImport,				config);
4161 		addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName,				"Test semaphores transference.",										testSemaphoreTransference,				config);
4162 
4163 		if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4164 			|| externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4165 		{
4166 			// \note Not supported on WIN32 handles
4167 			addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,	"Test exporting semaphore multiple times.",		testSemaphoreMultipleExports,	config);
4168 
4169 			addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName,						"Test calling dup() on exported semaphore.",	testSemaphoreFdDup,				config);
4170 			addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName,					"Test calling dup2() on exported semaphore.",	testSemaphoreFdDup2,			config);
4171 			addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName,					"Test calling dup3() on exported semaphore.",	testSemaphoreFdDup3,			config);
4172 			addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,		"Test sending semaphore fd over socket.",		testSemaphoreFdSendOverSocket,	config);
4173 		}
4174 
4175 		if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4176 		{
4177 			addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,			"Test signaling and then waiting for the the sepmahore.",				testSemaphoreSignalWaitImport,			config);
4178 			addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,	"Test exporting, signaling, importing and waiting for the semaphore.",	testSemaphoreExportSignalImportWait,	config);
4179 			addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,	"Test exporting, importing, signaling and waiting for the semaphore.",	testSemaphoreExportImportSignalWait,	config);
4180 		}
4181 	}
4182 
4183 	return semaphoreGroup;
4184 }
4185 
createSemaphoreTests(tcu::TestContext & testCtx)4186 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4187 {
4188 	de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4189 
4190 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4191 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4192 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4193 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4194 
4195 	return semaphoreGroup;
4196 }
4197 
createMemoryTests(tcu::TestContext & testCtx,vk::VkExternalMemoryHandleTypeFlagBits externalType)4198 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4199 {
4200 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4201 
4202 	for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4203 	{
4204 		const bool						dedicated		(dedicatedNdx == 1);
4205 		de::MovePtr<tcu::TestCaseGroup>	dedicatedGroup	(new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4206 
4207 		for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4208 		{
4209 			const bool						hostVisible			(hostVisibleNdx == 1);
4210 			de::MovePtr<tcu::TestCaseGroup>	hostVisibleGroup	(new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4211 			const MemoryTestConfig			memoryConfig		(externalType, hostVisible, dedicated);
4212 
4213 			if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4214 				|| externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4215 			{
4216 				addFunctionCase(hostVisibleGroup.get(), "create_win32",	"Test creating memory with win32 properties .",		testMemoryWin32Create,	memoryConfig);
4217 			}
4218 
4219 			addFunctionCase(hostVisibleGroup.get(), "import_twice",				"Test importing memory object twice.",			testMemoryImportTwice,		memoryConfig);
4220 			addFunctionCase(hostVisibleGroup.get(), "import_multiple_times",	"Test importing memory object multiple times.",	testMemoryMultimpleImports,	memoryConfig);
4221 
4222 			if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
4223 			{
4224 				addFunctionCase(hostVisibleGroup.get(), "dup",									"Test calling dup() on exported memory.",	testMemoryFdDup,			memoryConfig);
4225 				addFunctionCase(hostVisibleGroup.get(), "dup2",									"Test calling dup2() on exported memory.",	testMemoryFdDup2,			memoryConfig);
4226 				addFunctionCase(hostVisibleGroup.get(), "dup3",									"Test calling dup3() on exported memory.",	testMemoryFdDup3,			memoryConfig);
4227 				addFunctionCase(hostVisibleGroup.get(), "send_over_socket",						"Test sending memory fd over socket.",		testMemoryFdSendOverSocket,	memoryConfig);
4228 				// \note Not supported on WIN32 handles
4229 				addFunctionCase(hostVisibleGroup.get(), "export_multiple_times",				"Test exporting memory multiple times.",	testMemoryMultimpleExports,	memoryConfig);
4230 			}
4231 
4232 			dedicatedGroup->addChild(hostVisibleGroup.release());
4233 		}
4234 
4235 		{
4236 			de::MovePtr<tcu::TestCaseGroup>	bufferGroup		(new tcu::TestCaseGroup(testCtx, "buffer", ""));
4237 			const BufferTestConfig			bufferConfig	(externalType, dedicated);
4238 
4239 			addFunctionCase(bufferGroup.get(), "info",						"External buffer memory info query.",						testBufferQueries,				externalType);
4240 			addFunctionCase(bufferGroup.get(), "bind_export_import_bind",	"Test binding, exporting, importing and binding buffer.",	testBufferBindExportImportBind,	bufferConfig);
4241 			addFunctionCase(bufferGroup.get(), "export_bind_import_bind",	"Test exporting, binding, importing and binding buffer.",	testBufferExportBindImportBind,	bufferConfig);
4242 			addFunctionCase(bufferGroup.get(), "export_import_bind_bind",	"Test exporting, importind and binding buffer.",			testBufferExportImportBindBind,	bufferConfig);
4243 
4244 			dedicatedGroup->addChild(bufferGroup.release());
4245 		}
4246 
4247 		{
4248 			de::MovePtr<tcu::TestCaseGroup> imageGroup	(new tcu::TestCaseGroup(testCtx, "image", ""));
4249 			const ImageTestConfig			imageConfig	(externalType, dedicated);
4250 
4251 			addFunctionCase(imageGroup.get(), "info",						"External image memory info query.",						testImageQueries,				externalType);
4252 			addFunctionCase(imageGroup.get(), "bind_export_import_bind",	"Test binding, exporting, importing and binding image.",	testImageBindExportImportBind,	imageConfig);
4253 			addFunctionCase(imageGroup.get(), "export_bind_import_bind",	"Test exporting, binding, importing and binding image.",	testImageExportBindImportBind,	imageConfig);
4254 			addFunctionCase(imageGroup.get(), "export_import_bind_bind",	"Test exporting, importind and binding image.",				testImageExportImportBindBind,	imageConfig);
4255 
4256 			dedicatedGroup->addChild(imageGroup.release());
4257 		}
4258 
4259 		group->addChild(dedicatedGroup.release());
4260 	}
4261 
4262 	if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4263 	{
4264 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4265 
4266 		const vk::VkFormat	ahbFormats[]	=
4267 		{
4268 			vk::VK_FORMAT_R8G8B8_UNORM,
4269 			vk::VK_FORMAT_R8G8B8A8_UNORM,
4270 			vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4271 			vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4272 			vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4273 		};
4274 		const size_t		numOfAhbFormats	= DE_LENGTH_OF_ARRAY(ahbFormats);
4275 
4276 		for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4277 		{
4278 			const vk::VkFormat	format			= ahbFormats[ahbFormatNdx];
4279 			const std::string	testCaseName	= getFormatCaseName(format);
4280 
4281 			addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4282 		}
4283 
4284 		group->addChild(formatGroup.release());
4285 	}
4286 
4287 	return group;
4288 }
4289 
createMemoryTests(tcu::TestContext & testCtx)4290 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4291 {
4292 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4293 
4294 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4295 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4296 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4297 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4298 
4299 	return group;
4300 }
4301 
4302 } // anonymous
4303 
createExternalMemoryTests(tcu::TestContext & testCtx)4304 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4305 {
4306 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4307 
4308 	group->addChild(createSemaphoreTests(testCtx).release());
4309 	group->addChild(createMemoryTests(testCtx).release());
4310 	group->addChild(createFenceTests(testCtx).release());
4311 
4312 	return group.release();
4313 }
4314 
4315 } // api
4316 } // vkt
4317