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