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