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