• 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 signaled properly.
798 	if (nativeHandle.hasValidFd() && 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 
933 	// Allow -1, that is valid if signaled properly.
934 	if (nativeHandle.hasValidFd() && nativeHandle.getFd() == -1)
935 		TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
936 
937 	VK_CHECK(vk.queueWaitIdle(queue));
938 }
939 
940 struct TestSemaphoreQueriesParameters
941 {
942 	vk::VkSemaphoreType							semaphoreType;
943 	vk::VkExternalSemaphoreHandleTypeFlagBits	externalType;
944 
TestSemaphoreQueriesParametersvkt::api::__anon90dd3d8b0111::TestSemaphoreQueriesParameters945 	TestSemaphoreQueriesParameters (vk::VkSemaphoreType							semaphoreType_,
946 									vk::VkExternalSemaphoreHandleTypeFlagBits	externalType_)
947 		: semaphoreType	(semaphoreType_)
948 		, externalType	(externalType_)
949 	{}
950 };
951 
testSemaphoreQueries(Context & context,const TestSemaphoreQueriesParameters params)952 tcu::TestStatus testSemaphoreQueries (Context& context, const TestSemaphoreQueriesParameters params)
953 {
954 	const CustomInstance				instance		(createTestInstance(context, params.externalType, 0u, 0u));
955 	const vk::InstanceDriver&			vki				(instance.getDriver());
956 	const vk::VkPhysicalDevice			device			(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
957 
958 	TestLog&							log				= context.getTestContext().getLog();
959 
960 	const vk::VkSemaphoreTypeCreateInfo				semaphoreTypeInfo	=
961 	{
962 		vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
963 		DE_NULL,
964 		params.semaphoreType,
965 		0,
966 	};
967 	const vk::VkPhysicalDeviceExternalSemaphoreInfo	info				=
968 	{
969 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
970 		&semaphoreTypeInfo,
971 		params.externalType
972 	};
973 	vk::VkExternalSemaphoreProperties				properties			=
974 	{
975 		vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
976 		DE_NULL,
977 		0u,
978 		0u,
979 		0u
980 	};
981 
982 	vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
983 	log << TestLog::Message << properties << TestLog::EndMessage;
984 
985 	TCU_CHECK(properties.pNext == DE_NULL);
986 	TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
987 
988 	if (params.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE)
989 	{
990 		context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
991 
992 		if (properties.compatibleHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
993 			return tcu::TestStatus::fail("Timeline semaphores are not compatible with SYNC_FD");
994 
995 		if (properties.exportFromImportedHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
996 			return tcu::TestStatus::fail("Timeline semaphores imported from SYNC_FD");
997 	}
998 
999 	return tcu::TestStatus::pass("Pass");
1000 }
1001 
1002 struct SemaphoreTestConfig
1003 {
SemaphoreTestConfigvkt::api::__anon90dd3d8b0111::SemaphoreTestConfig1004 													SemaphoreTestConfig	(vk::VkExternalSemaphoreHandleTypeFlagBits	externalType_,
1005 																		 Permanence										permanence_)
1006 		: externalType		(externalType_)
1007 		, permanence		(permanence_)
1008 	{
1009 	}
1010 
1011 	vk::VkExternalSemaphoreHandleTypeFlagBits	externalType;
1012 	Permanence									permanence;
1013 };
1014 
initProgramsToGetNativeFd(vk::SourceCollections & dst,const TestConfig)1015 template<class TestConfig> void initProgramsToGetNativeFd(vk::SourceCollections& dst, const TestConfig)
1016 {
1017 	const tcu::IVec3 localSize = { 64, 1, 1 };
1018 
1019 	std::ostringstream src;
1020 	src << "#version 310 es\n"
1021 		<< "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y() << ", local_size_z = " << localSize.z() << ") in;\n"
1022 		<< "layout(binding = 0) writeonly buffer Output {\n"
1023 		<< "    uint values[];\n"
1024 		<< "};\n"
1025 		<< "\n"
1026 		<< "void main (void) {\n"
1027 		<< "    uint offset = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1028 		<< "\n"
1029 		<< "      atomicAdd(values[offset], 1u);\n"
1030 		<< "}\n";
1031 
1032 	dst.glslSources.add("compute") << glu::ComputeSource(src.str());
1033 }
1034 
testSemaphoreWin32Create(Context & context,const SemaphoreTestConfig config)1035 tcu::TestStatus testSemaphoreWin32Create (Context&					context,
1036 										  const SemaphoreTestConfig	config)
1037 {
1038 #if (DE_OS == DE_OS_WIN32)
1039 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1040 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1041 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1042 	const vk::InstanceDriver&			vki					(instance.getDriver());
1043 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1044 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1045 
1046 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1047 
1048 	{
1049 		const vk::Unique<vk::VkDevice>					device			(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1050 		const vk::DeviceDriver							vkd				(vkp, instance, *device);
1051 		const vk::VkQueue								queue			(getQueue(vkd, *device, queueFamilyIndex));
1052 		const vk::VkExportSemaphoreWin32HandleInfoKHR	win32ExportInfo	=
1053 		{
1054 			vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
1055 			DE_NULL,
1056 
1057 			(vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1058 			DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1059 			(vk::pt::Win32LPCWSTR)DE_NULL
1060 		};
1061 		const vk::VkExportSemaphoreCreateInfo			exportCreateInfo=
1062 		{
1063 			vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
1064 			&win32ExportInfo,
1065 			(vk::VkExternalMemoryHandleTypeFlags)config.externalType
1066 		};
1067 		const vk::VkSemaphoreCreateInfo					createInfo		=
1068 		{
1069 			vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1070 			&exportCreateInfo,
1071 			0u
1072 		};
1073 		const vk::Unique<vk::VkSemaphore>				semaphore		(vk::createSemaphore(vkd, *device, &createInfo));
1074 
1075 		if (transference == TRANSFERENCE_COPY)
1076 			submitEmptySignal(vkd, queue, *semaphore);
1077 
1078 		NativeHandle									handleA;
1079 		getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1080 
1081 		{
1082 			const vk::VkSemaphoreImportFlags			flags			= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1083 			const vk::Unique<vk::VkSemaphore>			semaphoreA		(createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1084 
1085 			if (transference == TRANSFERENCE_COPY)
1086 				submitEmptyWait(vkd, queue, *semaphoreA);
1087 			else if (transference == TRANSFERENCE_REFERENCE)
1088 			{
1089 				submitEmptySignal(vkd, queue, *semaphore);
1090 				submitEmptyWait(vkd, queue, *semaphoreA);
1091 			}
1092 			else
1093 				DE_FATAL("Unknown transference.");
1094 
1095 			VK_CHECK(vkd.queueWaitIdle(queue));
1096 		}
1097 
1098 		return tcu::TestStatus::pass("Pass");
1099 	}
1100 #else
1101 	DE_UNREF(context);
1102 	DE_UNREF(config);
1103 	TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1104 #endif
1105 }
1106 
testSemaphoreImportTwice(Context & context,const SemaphoreTestConfig config)1107 tcu::TestStatus testSemaphoreImportTwice (Context&					context,
1108 										  const SemaphoreTestConfig	config)
1109 {
1110 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1111 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1112 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1113 	const vk::InstanceDriver&			vki					(instance.getDriver());
1114 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1115 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1116 
1117 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1118 
1119 	{
1120 		const vk::Unique<vk::VkDevice>		device			(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1121 		const vk::DeviceDriver				vkd				(vkp, instance, *device);
1122 		vk::SimpleAllocator					alloc			(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1123 		const vk::VkQueue					queue			(getQueue(vkd, *device, queueFamilyIndex));
1124 		const vk::Unique<vk::VkSemaphore>	semaphore		(createExportableSemaphore(vkd, *device, config.externalType));
1125 		NativeHandle						handleA;
1126 
1127 		if (transference == TRANSFERENCE_COPY)
1128 		{
1129 			submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
1130 			if (handleA.hasValidFd() && handleA.getFd() == -1)
1131 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1132 		}
1133 		else
1134 			getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1135 
1136 		{
1137 			NativeHandle						handleB		(handleA);
1138 			const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1139 			const vk::Unique<vk::VkSemaphore>	semaphoreA	(createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1140 			const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1141 
1142 			if (transference == TRANSFERENCE_COPY)
1143 				submitEmptyWait(vkd, queue, *semaphoreA);
1144 			else if (transference == TRANSFERENCE_REFERENCE)
1145 			{
1146 				submitEmptySignal(vkd, queue, *semaphoreA);
1147 				submitEmptyWait(vkd, queue, *semaphoreB);
1148 			}
1149 			else
1150 				DE_FATAL("Unknown transference.");
1151 
1152 			VK_CHECK(vkd.queueWaitIdle(queue));
1153 		}
1154 
1155 		return tcu::TestStatus::pass("Pass");
1156 	}
1157 }
1158 
testSemaphoreImportReimport(Context & context,const SemaphoreTestConfig config)1159 tcu::TestStatus testSemaphoreImportReimport (Context&					context,
1160 											 const SemaphoreTestConfig	config)
1161 {
1162 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1163 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1164 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1165 	const vk::InstanceDriver&			vki					(instance.getDriver());
1166 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1167 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1168 
1169 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1170 
1171 	{
1172 		const vk::Unique<vk::VkDevice>		device			(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1173 		const vk::DeviceDriver				vkd				(vkp, instance, *device);
1174 		vk::SimpleAllocator					alloc			(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1175 		const vk::VkQueue					queue			(getQueue(vkd, *device, queueFamilyIndex));
1176 
1177 		const vk::Unique<vk::VkSemaphore>	semaphoreA		(createExportableSemaphore(vkd, *device, config.externalType));
1178 		NativeHandle						handleA;
1179 
1180 		if (transference == TRANSFERENCE_COPY)
1181 		{
1182 			submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1183 			if (handleA.hasValidFd() && handleA.getFd() == -1)
1184 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1185 		}
1186 		else
1187 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1188 
1189 		NativeHandle						handleB		(handleA);
1190 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1191 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1192 
1193 		importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
1194 
1195 		if (transference == TRANSFERENCE_COPY)
1196 			submitEmptyWait(vkd, queue, *semaphoreB);
1197 		else if (transference == TRANSFERENCE_REFERENCE)
1198 		{
1199 			submitEmptySignal(vkd, queue, *semaphoreA);
1200 			submitEmptyWait(vkd, queue, *semaphoreB);
1201 		}
1202 		else
1203 			DE_FATAL("Unknown transference.");
1204 
1205 		VK_CHECK(vkd.queueWaitIdle(queue));
1206 
1207 		return tcu::TestStatus::pass("Pass");
1208 	}
1209 }
1210 
testSemaphoreSignalExportImportWait(Context & context,const SemaphoreTestConfig config)1211 tcu::TestStatus testSemaphoreSignalExportImportWait (Context&					context,
1212 													 const SemaphoreTestConfig	config)
1213 {
1214 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1215 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1216 	const vk::InstanceDriver&			vki					(instance.getDriver());
1217 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1218 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1219 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1220 
1221 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1222 
1223 	{
1224 		const vk::Unique<vk::VkDevice>		device				(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1225 		const vk::DeviceDriver				vkd					(vkp, instance, *device);
1226 		vk::SimpleAllocator					alloc				(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1227 		const vk::VkQueue					queue				(getQueue(vkd, *device, queueFamilyIndex));
1228 		const vk::Unique<vk::VkSemaphore>	semaphoreA			(createExportableSemaphore(vkd, *device, config.externalType));
1229 		{
1230 			NativeHandle	handle;
1231 
1232 			submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1233 			if (transference == TRANSFERENCE_COPY && handle.hasValidFd() && handle.getFd() == -1)
1234 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1235 
1236 			{
1237 				const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1238 				const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1239 				submitEmptyWait(vkd, queue, *semaphoreB);
1240 
1241 				VK_CHECK(vkd.queueWaitIdle(queue));
1242 			}
1243 		}
1244 
1245 		return tcu::TestStatus::pass("Pass");
1246 	}
1247 }
1248 
testSemaphoreExportSignalImportWait(Context & context,const SemaphoreTestConfig config)1249 tcu::TestStatus testSemaphoreExportSignalImportWait (Context&					context,
1250 													 const SemaphoreTestConfig	config)
1251 {
1252 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1253 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1254 	const vk::InstanceDriver&			vki					(instance.getDriver());
1255 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1256 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1257 	const vk::VkSemaphoreImportFlags	flags				= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1258 
1259 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1260 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1261 
1262 	{
1263 		const vk::Unique<vk::VkDevice>		device				(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1264 		const vk::DeviceDriver				vkd					(vkp, instance, *device);
1265 		const vk::VkQueue					queue				(getQueue(vkd, *device, queueFamilyIndex));
1266 
1267 		const vk::Unique<vk::VkSemaphore>	semaphoreA			(createExportableSemaphore(vkd, *device, config.externalType));
1268 		NativeHandle						handle;
1269 
1270 		getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1271 
1272 		submitEmptySignal(vkd, queue, *semaphoreA);
1273 		{
1274 			{
1275 				const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1276 
1277 				submitEmptyWait(vkd, queue, *semaphoreB);
1278 				VK_CHECK(vkd.queueWaitIdle(queue));
1279 			}
1280 		}
1281 
1282 		return tcu::TestStatus::pass("Pass");
1283 	}
1284 }
1285 
testSemaphoreExportImportSignalWait(Context & context,const SemaphoreTestConfig config)1286 tcu::TestStatus testSemaphoreExportImportSignalWait (Context&					context,
1287 													 const SemaphoreTestConfig	config)
1288 {
1289 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1290 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1291 	const vk::InstanceDriver&			vki					(instance.getDriver());
1292 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1293 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1294 
1295 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1296 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1297 
1298 	{
1299 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1300 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1301 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1302 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1303 
1304 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1305 		NativeHandle						handle;
1306 
1307 		getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1308 
1309 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1310 
1311 		submitEmptySignal(vkd, queue, *semaphoreA);
1312 		submitEmptyWait(vkd, queue, *semaphoreB);
1313 
1314 		VK_CHECK(vkd.queueWaitIdle(queue));
1315 
1316 		return tcu::TestStatus::pass("Pass");
1317 	}
1318 }
1319 
testSemaphoreSignalImport(Context & context,const SemaphoreTestConfig config)1320 tcu::TestStatus testSemaphoreSignalImport (Context&						context,
1321 										   const SemaphoreTestConfig	config)
1322 {
1323 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1324 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1325 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1326 	const vk::InstanceDriver&			vki					(instance.getDriver());
1327 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1328 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1329 
1330 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1331 
1332 	{
1333 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1334 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1335 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1336 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1337 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1338 
1339 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1340 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createSemaphore(vkd, *device));
1341 		NativeHandle						handle;
1342 
1343 		submitEmptySignal(vkd, queue, *semaphoreB);
1344 		VK_CHECK(vkd.queueWaitIdle(queue));
1345 
1346 		if (transference == TRANSFERENCE_COPY)
1347 		{
1348 			submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1349 			if (handle.hasValidFd() && handle.getFd() == -1)
1350 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1351 		}
1352 		else
1353 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1354 
1355 		importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1356 
1357 		if (transference == TRANSFERENCE_COPY)
1358 			submitEmptyWait(vkd, queue, *semaphoreB);
1359 		else if (transference == TRANSFERENCE_REFERENCE)
1360 		{
1361 			submitEmptySignal(vkd, queue, *semaphoreA);
1362 			submitEmptyWait(vkd, queue, *semaphoreB);
1363 		}
1364 		else
1365 			DE_FATAL("Unknown transference.");
1366 
1367 		VK_CHECK(vkd.queueWaitIdle(queue));
1368 
1369 		return tcu::TestStatus::pass("Pass");
1370 	}
1371 }
1372 
testSemaphoreSignalWaitImport(Context & context,const SemaphoreTestConfig config)1373 tcu::TestStatus testSemaphoreSignalWaitImport (Context&						context,
1374 											   const SemaphoreTestConfig	config)
1375 {
1376 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1377 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1378 	const vk::InstanceDriver&			vki					(instance.getDriver());
1379 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1380 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1381 
1382 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1383 
1384 	{
1385 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1386 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1387 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1388 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1389 
1390 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1391 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createSemaphore(vkd, *device));
1392 		NativeHandle						handle;
1393 
1394 		getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1395 
1396 		submitEmptySignal(vkd, queue, *semaphoreB);
1397 		submitEmptyWait(vkd, queue, *semaphoreB);
1398 
1399 		VK_CHECK(vkd.queueWaitIdle(queue));
1400 
1401 		importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1402 
1403 		submitEmptySignal(vkd, queue, *semaphoreA);
1404 		submitEmptyWait(vkd, queue, *semaphoreB);
1405 
1406 		VK_CHECK(vkd.queueWaitIdle(queue));
1407 
1408 		return tcu::TestStatus::pass("Pass");
1409 	}
1410 }
1411 
testSemaphoreImportSyncFdSignaled(Context & context,const SemaphoreTestConfig config)1412 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context&						context,
1413 												   const SemaphoreTestConfig	config)
1414 {
1415 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1416 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1417 	const vk::InstanceDriver&			vki					(instance.getDriver());
1418 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1419 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1420 	const vk::VkSemaphoreImportFlags	flags				= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1421 
1422 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1423 
1424 	{
1425 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1426 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1427 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1428 		NativeHandle						handle		= -1;
1429 		const vk::Unique<vk::VkSemaphore>	semaphore	(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1430 
1431 		submitEmptyWait(vkd, queue, *semaphore);
1432 		VK_CHECK(vkd.queueWaitIdle(queue));
1433 
1434 		return tcu::TestStatus::pass("Pass");
1435 	}
1436 }
1437 
testSemaphoreMultipleExports(Context & context,const SemaphoreTestConfig config)1438 tcu::TestStatus testSemaphoreMultipleExports (Context&					context,
1439 											  const SemaphoreTestConfig	config)
1440 {
1441 	const size_t						exportCount			= 1024;
1442 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1443 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1444 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1445 	const vk::InstanceDriver&			vki					(instance.getDriver());
1446 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1447 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1448 
1449 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1450 
1451 	{
1452 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1453 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1454 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1455 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1456 		const vk::Unique<vk::VkSemaphore>	semaphore	(createExportableSemaphore(vkd, *device, config.externalType));
1457 
1458 		for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1459 		{
1460 			NativeHandle handle;
1461 
1462 			// Need to touch watchdog due to how long one iteration takes
1463 			context.getTestContext().touchWatchdog();
1464 
1465 			if (transference == TRANSFERENCE_COPY)
1466 			{
1467 				submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1468 				if (handle.hasValidFd() && handle.getFd() == -1)
1469 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1470 			}
1471 			else
1472 				getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1473 		}
1474 
1475 		submitEmptySignal(vkd, queue, *semaphore);
1476 		submitEmptyWait(vkd, queue, *semaphore);
1477 
1478 		VK_CHECK(vkd.queueWaitIdle(queue));
1479 	}
1480 
1481 	return tcu::TestStatus::pass("Pass");
1482 }
1483 
testSemaphoreMultipleImports(Context & context,const SemaphoreTestConfig config)1484 tcu::TestStatus testSemaphoreMultipleImports (Context&					context,
1485 											  const SemaphoreTestConfig	config)
1486 {
1487 	const size_t						importCount			= 4 * 1024;
1488 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1489 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1490 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1491 	const vk::InstanceDriver&			vki					(instance.getDriver());
1492 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1493 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1494 
1495 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1496 
1497 	{
1498 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1499 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1500 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1501 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1502 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1503 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1504 		NativeHandle						handleA;
1505 
1506 		if (transference == TRANSFERENCE_COPY)
1507 		{
1508 			submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1509 			if (handleA.hasValidFd() && handleA.getFd() == -1)
1510 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1511 		}
1512 		else
1513 			getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1514 
1515 		for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1516 		{
1517 			NativeHandle						handleB		(handleA);
1518 			const vk::Unique<vk::VkSemaphore>	semaphoreB	(createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1519 		}
1520 
1521 		if (transference == TRANSFERENCE_COPY)
1522 		{
1523 			importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1524 			submitEmptyWait(vkd, queue, *semaphoreA);
1525 		}
1526 		else if (transference == TRANSFERENCE_REFERENCE)
1527 		{
1528 			submitEmptySignal(vkd, queue, *semaphoreA);
1529 			submitEmptyWait(vkd, queue, *semaphoreA);
1530 		}
1531 		else
1532 			DE_FATAL("Unknown transference.");
1533 
1534 		VK_CHECK(vkd.queueWaitIdle(queue));
1535 	}
1536 
1537 	return tcu::TestStatus::pass("Pass");
1538 }
1539 
testSemaphoreTransference(Context & context,const SemaphoreTestConfig config)1540 tcu::TestStatus testSemaphoreTransference (Context&						context,
1541 										   const SemaphoreTestConfig	config)
1542 {
1543 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1544 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1545 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1546 	const vk::InstanceDriver&			vki					(instance.getDriver());
1547 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1548 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1549 
1550 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1551 
1552 	{
1553 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1554 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context,  vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1555 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1556 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1557 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1558 
1559 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1560 		NativeHandle						handle;
1561 
1562 		submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1563 		if (transference == TRANSFERENCE_COPY && handle.hasValidFd() && handle.getFd() == -1)
1564 			return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1565 
1566 		{
1567 			const vk::Unique<vk::VkSemaphore>	semaphoreB			(createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1568 
1569 			if (config.permanence == PERMANENCE_PERMANENT)
1570 			{
1571 				if (transference == TRANSFERENCE_COPY)
1572 				{
1573 					submitEmptySignal(vkd, queue, *semaphoreA);
1574 					submitEmptyWait(vkd, queue, *semaphoreB);
1575 					VK_CHECK(vkd.queueWaitIdle(queue));
1576 
1577 					submitEmptySignal(vkd, queue, *semaphoreB);
1578 
1579 					submitEmptyWait(vkd, queue, *semaphoreA);
1580 					submitEmptyWait(vkd, queue, *semaphoreB);
1581 					VK_CHECK(vkd.queueWaitIdle(queue));
1582 				}
1583 				else if (transference== TRANSFERENCE_REFERENCE)
1584 				{
1585 					submitEmptyWait(vkd, queue, *semaphoreB);
1586 					VK_CHECK(vkd.queueWaitIdle(queue));
1587 
1588 					submitEmptySignal(vkd, queue, *semaphoreA);
1589 					submitEmptyWait(vkd, queue, *semaphoreB);
1590 
1591 					submitEmptySignal(vkd, queue, *semaphoreB);
1592 					submitEmptyWait(vkd, queue, *semaphoreA);
1593 					VK_CHECK(vkd.queueWaitIdle(queue));
1594 				}
1595 				else
1596 					DE_FATAL("Unknown transference.");
1597 			}
1598 			else if (config.permanence == PERMANENCE_TEMPORARY)
1599 			{
1600 				if (transference == TRANSFERENCE_COPY)
1601 				{
1602 					submitEmptySignal(vkd, queue, *semaphoreA);
1603 					submitEmptyWait(vkd, queue, *semaphoreB);
1604 					VK_CHECK(vkd.queueWaitIdle(queue));
1605 
1606 					submitEmptySignal(vkd, queue, *semaphoreB);
1607 
1608 					submitEmptyWait(vkd, queue, *semaphoreA);
1609 					submitEmptyWait(vkd, queue, *semaphoreB);
1610 					VK_CHECK(vkd.queueWaitIdle(queue));
1611 				}
1612 				else if (transference== TRANSFERENCE_REFERENCE)
1613 				{
1614 					submitEmptyWait(vkd, queue, *semaphoreB);
1615 					VK_CHECK(vkd.queueWaitIdle(queue));
1616 
1617 					submitEmptySignal(vkd, queue, *semaphoreA);
1618 					submitEmptySignal(vkd, queue, *semaphoreB);
1619 
1620 					submitEmptyWait(vkd, queue, *semaphoreB);
1621 					submitEmptyWait(vkd, queue, *semaphoreA);
1622 					VK_CHECK(vkd.queueWaitIdle(queue));
1623 				}
1624 				else
1625 					DE_FATAL("Unknown transference.");
1626 			}
1627 			else
1628 				DE_FATAL("Unknown permanence.");
1629 		}
1630 
1631 		return tcu::TestStatus::pass("Pass");
1632 	}
1633 }
1634 
testSemaphoreFdDup(Context & context,const SemaphoreTestConfig config)1635 tcu::TestStatus testSemaphoreFdDup (Context&					context,
1636 									const SemaphoreTestConfig	config)
1637 {
1638 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1639 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1640 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1641 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1642 	const vk::InstanceDriver&			vki					(instance.getDriver());
1643 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1644 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1645 
1646 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1647 
1648 	{
1649 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1650 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1651 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1652 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1653 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1654 
1655 		TestLog&							log			= context.getTestContext().getLog();
1656 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1657 
1658 		{
1659 			NativeHandle		fd;
1660 
1661 			if (transference == TRANSFERENCE_COPY)
1662 			{
1663 				submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1664 				if (fd.getFd() == -1)
1665 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1666 			}
1667 			else
1668 				getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1669 
1670 			NativeHandle		newFd	(dup(fd.getFd()));
1671 
1672 			if (newFd.getFd() < 0)
1673 				log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1674 
1675 			TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1676 
1677 			{
1678 				const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1679 
1680 				if (transference == TRANSFERENCE_COPY)
1681 					submitEmptyWait(vkd, queue, *semaphoreB);
1682 				else if (transference == TRANSFERENCE_REFERENCE)
1683 				{
1684 					submitEmptySignal(vkd, queue, *semaphoreA);
1685 					submitEmptyWait(vkd, queue, *semaphoreB);
1686 				}
1687 				else
1688 					DE_FATAL("Unknown permanence.");
1689 
1690 				VK_CHECK(vkd.queueWaitIdle(queue));
1691 			}
1692 		}
1693 
1694 		return tcu::TestStatus::pass("Pass");
1695 	}
1696 #else
1697 	DE_UNREF(context);
1698 	DE_UNREF(config);
1699 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1700 #endif
1701 }
1702 
testSemaphoreFdDup2(Context & context,const SemaphoreTestConfig config)1703 tcu::TestStatus testSemaphoreFdDup2 (Context&					context,
1704 									 const SemaphoreTestConfig	config)
1705 {
1706 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1707 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1708 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1709 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1710 	const vk::InstanceDriver&			vki					(instance.getDriver());
1711 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1712 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1713 
1714 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1715 
1716 	{
1717 		const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1718 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1719 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1720 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1721 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1722 
1723 		TestLog&							log			= context.getTestContext().getLog();
1724 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1725 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createExportableSemaphore(vkd, *device, config.externalType));
1726 
1727 		{
1728 			NativeHandle		fd, secondFd;
1729 
1730 			if (transference == TRANSFERENCE_COPY)
1731 			{
1732 				submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1733 				submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1734 				if (fd.getFd() == -1 || secondFd.getFd() == -1)
1735 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1736 			}
1737 			else
1738 			{
1739 				getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1740 				getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1741 			}
1742 
1743 			int					newFd		(dup2(fd.getFd(), secondFd.getFd()));
1744 
1745 			if (newFd < 0)
1746 				log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1747 
1748 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1749 
1750 			{
1751 				const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1752 
1753 				if (transference == TRANSFERENCE_COPY)
1754 					submitEmptyWait(vkd, queue, *semaphoreC);
1755 				else if (transference == TRANSFERENCE_REFERENCE)
1756 				{
1757 					submitEmptySignal(vkd, queue, *semaphoreA);
1758 					submitEmptyWait(vkd, queue, *semaphoreC);
1759 				}
1760 				else
1761 					DE_FATAL("Unknown permanence.");
1762 
1763 				VK_CHECK(vkd.queueWaitIdle(queue));
1764 			}
1765 		}
1766 
1767 		return tcu::TestStatus::pass("Pass");
1768 	}
1769 #else
1770 	DE_UNREF(context);
1771 	DE_UNREF(config);
1772 	TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1773 #endif
1774 }
1775 
testSemaphoreFdDup3(Context & context,const SemaphoreTestConfig config)1776 tcu::TestStatus testSemaphoreFdDup3 (Context&					context,
1777 									 const SemaphoreTestConfig	config)
1778 {
1779 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1780 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1781 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1782 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1783 	const vk::InstanceDriver&			vki					(instance.getDriver());
1784 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1785 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1786 
1787 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1788 
1789 	{
1790 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1791 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1792 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1793 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1794 
1795 		TestLog&							log			= context.getTestContext().getLog();
1796 		const vk::Unique<vk::VkSemaphore>	semaphoreA	(createExportableSemaphore(vkd, *device, config.externalType));
1797 		const vk::Unique<vk::VkSemaphore>	semaphoreB	(createExportableSemaphore(vkd, *device, config.externalType));
1798 
1799 		{
1800 			NativeHandle						fd, secondFd;
1801 
1802 			if (transference == TRANSFERENCE_COPY)
1803 			{
1804 				submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1805 				submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1806 				if (fd.getFd() == -1 || secondFd.getFd() == -1)
1807 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1808 			}
1809 			else
1810 			{
1811 				getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1812 				getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1813 			}
1814 
1815 			const vk::VkSemaphoreImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1816 			const int							newFd		(dup3(fd.getFd(), secondFd.getFd(), 0));
1817 
1818 			if (newFd < 0)
1819 				log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1820 
1821 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1822 
1823 			{
1824 				const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1825 
1826 				if (transference == TRANSFERENCE_COPY)
1827 					submitEmptyWait(vkd, queue, *semaphoreC);
1828 				else if (transference == TRANSFERENCE_REFERENCE)
1829 				{
1830 					submitEmptySignal(vkd, queue, *semaphoreA);
1831 					submitEmptyWait(vkd, queue, *semaphoreC);
1832 				}
1833 				else
1834 					DE_FATAL("Unknown permanence.");
1835 
1836 				VK_CHECK(vkd.queueWaitIdle(queue));
1837 			}
1838 		}
1839 
1840 		return tcu::TestStatus::pass("Pass");
1841 	}
1842 #else
1843 	DE_UNREF(context);
1844 	DE_UNREF(config);
1845 	TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1846 #endif
1847 }
1848 
testSemaphoreFdSendOverSocket(Context & context,const SemaphoreTestConfig config)1849 tcu::TestStatus testSemaphoreFdSendOverSocket (Context&						context,
1850 											   const SemaphoreTestConfig	config)
1851 {
1852 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1853 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
1854 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
1855 	const CustomInstance				instance			(createTestInstance(context, config.externalType, 0u, 0u));
1856 	const vk::InstanceDriver&			vki					(instance.getDriver());
1857 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1858 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1859 
1860 	checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1861 
1862 	{
1863 		const vk::Unique<vk::VkDevice>		device		(createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1864 		const vk::DeviceDriver				vkd			(vkp, instance, *device);
1865 		vk::SimpleAllocator					alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1866 		const vk::VkQueue					queue		(getQueue(vkd, *device, queueFamilyIndex));
1867 
1868 		TestLog&							log			= context.getTestContext().getLog();
1869 		const vk::Unique<vk::VkSemaphore>	semaphore	(createExportableSemaphore(vkd, *device, config.externalType));
1870 		NativeHandle						fd;
1871 
1872 		if (transference == TRANSFERENCE_COPY)
1873 		{
1874 			submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1875 			if (fd.getFd() == -1)
1876 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1877 		}
1878 		else
1879 			getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1880 
1881 		{
1882 			int sv[2];
1883 
1884 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1885 			{
1886 				log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1887 				TCU_FAIL("Failed to create socket pair");
1888 			}
1889 
1890 			{
1891 				const NativeHandle	srcSocket	(sv[0]);
1892 				const NativeHandle	dstSocket	(sv[1]);
1893 				std::string			sendData	("deqp");
1894 
1895 				// Send FD
1896 				{
1897 					const int			fdRaw	(fd.getFd());
1898 					msghdr				msg;
1899 					cmsghdr*			cmsg;
1900 					char				buffer[CMSG_SPACE(sizeof(int))];
1901 					iovec				iov		= { &sendData[0], sendData.length()};
1902 
1903 					deMemset(&msg, 0, sizeof(msg));
1904 
1905 					msg.msg_control		= buffer;
1906 					msg.msg_controllen	= sizeof(buffer);
1907 					msg.msg_iovlen		= 1;
1908 					msg.msg_iov			= &iov;
1909 
1910 					cmsg				= CMSG_FIRSTHDR(&msg);
1911 					cmsg->cmsg_level	= SOL_SOCKET;
1912 					cmsg->cmsg_type		= SCM_RIGHTS;
1913 					cmsg->cmsg_len		= CMSG_LEN(sizeof(int));
1914 
1915 					deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1916 					msg.msg_controllen = cmsg->cmsg_len;
1917 
1918 					if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1919 					{
1920 						log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1921 						TCU_FAIL("Failed to send fd over socket");
1922 					}
1923 				}
1924 
1925 				// Recv FD
1926 				{
1927 					msghdr			msg;
1928 					char			buffer[CMSG_SPACE(sizeof(int))];
1929 					std::string		recvData	(4, '\0');
1930 					iovec			iov			= { &recvData[0], recvData.length() };
1931 
1932 					deMemset(&msg, 0, sizeof(msg));
1933 
1934 					msg.msg_control		= buffer;
1935 					msg.msg_controllen	= sizeof(buffer);
1936 					msg.msg_iovlen		= 1;
1937 					msg.msg_iov			= &iov;
1938 
1939 					const ssize_t	bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1940 
1941 					if (bytes < 0)
1942 					{
1943 						log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1944 						TCU_FAIL("Failed to recv fd over socket");
1945 
1946 					}
1947 					else if (bytes != (ssize_t)sendData.length())
1948 					{
1949 						TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1950 					}
1951 					else
1952 					{
1953 						const vk::VkSemaphoreImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1954 						const cmsghdr* const				cmsg	= CMSG_FIRSTHDR(&msg);
1955 						int									newFd_;
1956 						deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1957 						NativeHandle						newFd	(newFd_);
1958 
1959 						TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1960 						TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1961 						TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1962 						TCU_CHECK(recvData == sendData);
1963 						TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1964 
1965 						{
1966 							const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1967 
1968 							if (transference == TRANSFERENCE_COPY)
1969 								submitEmptyWait(vkd, queue, *newSemaphore);
1970 							else if (transference == TRANSFERENCE_REFERENCE)
1971 							{
1972 								submitEmptySignal(vkd, queue, *newSemaphore);
1973 								submitEmptyWait(vkd, queue, *newSemaphore);
1974 							}
1975 							else
1976 								DE_FATAL("Unknown permanence.");
1977 
1978 							VK_CHECK(vkd.queueWaitIdle(queue));
1979 						}
1980 					}
1981 				}
1982 			}
1983 		}
1984 	}
1985 
1986 	return tcu::TestStatus::pass("Pass");
1987 #else
1988 	DE_UNREF(context);
1989 	DE_UNREF(config);
1990 	TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1991 #endif
1992 }
1993 
testFenceQueries(Context & context,vk::VkExternalFenceHandleTypeFlagBits externalType)1994 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1995 {
1996 	const CustomInstance							instance	(createTestInstance(context, 0u, 0u, externalType));
1997 	const vk::InstanceDriver&						vki			(instance.getDriver());
1998 	const vk::VkPhysicalDevice						device		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1999 
2000 	TestLog&										log			= context.getTestContext().getLog();
2001 
2002 	const vk::VkPhysicalDeviceExternalFenceInfo		info		=
2003 	{
2004 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
2005 		DE_NULL,
2006 		externalType
2007 	};
2008 	vk::VkExternalFenceProperties					properties	=
2009 	{
2010 		vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
2011 		DE_NULL,
2012 		0u,
2013 		0u,
2014 		0u
2015 	};
2016 
2017 	vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
2018 	log << TestLog::Message << properties << TestLog::EndMessage;
2019 
2020 	TCU_CHECK(properties.pNext == DE_NULL);
2021 	TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
2022 
2023 	return tcu::TestStatus::pass("Pass");
2024 }
2025 
2026 struct FenceTestConfig
2027 {
FenceTestConfigvkt::api::__anon90dd3d8b0111::FenceTestConfig2028 												FenceTestConfig	(vk::VkExternalFenceHandleTypeFlagBits	externalType_,
2029 																 Permanence									permanence_)
2030 		: externalType		(externalType_)
2031 		, permanence		(permanence_)
2032 	{
2033 	}
2034 
2035 	vk::VkExternalFenceHandleTypeFlagBits	externalType;
2036 	Permanence								permanence;
2037 };
2038 
testFenceWin32Create(Context & context,const FenceTestConfig config)2039 tcu::TestStatus testFenceWin32Create (Context&				context,
2040 									  const FenceTestConfig	config)
2041 {
2042 #if (DE_OS == DE_OS_WIN32)
2043 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2044 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2045 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2046 	const vk::InstanceDriver&			vki					(instance.getDriver());
2047 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2048 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2049 
2050 	checkFenceSupport(vki, physicalDevice, config.externalType);
2051 
2052 	{
2053 		const vk::Unique<vk::VkDevice>				device			(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2054 		const vk::DeviceDriver						vkd				(vkp, instance, *device);
2055 		const vk::VkQueue							queue			(getQueue(vkd, *device, queueFamilyIndex));
2056 		const vk::VkExportFenceWin32HandleInfoKHR	win32ExportInfo	=
2057 		{
2058 			vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
2059 			DE_NULL,
2060 
2061 			(vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2062 			DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2063 			(vk::pt::Win32LPCWSTR)DE_NULL
2064 		};
2065 		const vk::VkExportFenceCreateInfo			exportCreateInfo=
2066 		{
2067 			vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
2068 			&win32ExportInfo,
2069 			(vk::VkExternalFenceHandleTypeFlags)config.externalType
2070 		};
2071 		const vk::VkFenceCreateInfo					createInfo		=
2072 		{
2073 			vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
2074 			&exportCreateInfo,
2075 			0u
2076 		};
2077 		const vk::Unique<vk::VkFence>				fence			(vk::createFence(vkd, *device, &createInfo));
2078 
2079 		if (transference == TRANSFERENCE_COPY)
2080 			submitEmptySignal(vkd, queue, *fence);
2081 
2082 		NativeHandle								handleA;
2083 		getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2084 
2085 		{
2086 			const vk::VkFenceImportFlags			flags			= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2087 			const vk::Unique<vk::VkFence>			fenceA			(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2088 
2089 			if (transference == TRANSFERENCE_COPY)
2090 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2091 			else if (transference == TRANSFERENCE_REFERENCE)
2092 			{
2093 				submitEmptySignal(vkd, queue, *fence);
2094 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2095 			}
2096 			else
2097 				DE_FATAL("Unknown transference.");
2098 
2099 			VK_CHECK(vkd.queueWaitIdle(queue));
2100 		}
2101 
2102 		return tcu::TestStatus::pass("Pass");
2103 	}
2104 #else
2105 	DE_UNREF(context);
2106 	DE_UNREF(config);
2107 	TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2108 #endif
2109 }
2110 
testFenceImportTwice(Context & context,const FenceTestConfig config)2111 tcu::TestStatus testFenceImportTwice (Context&				context,
2112 									  const FenceTestConfig	config)
2113 {
2114 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2115 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2116 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2117 	const vk::InstanceDriver&			vki					(instance.getDriver());
2118 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2119 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2120 
2121 	checkFenceSupport(vki, physicalDevice, config.externalType);
2122 
2123 	{
2124 		const vk::Unique<vk::VkDevice>	device		(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2125 		const vk::DeviceDriver			vkd			(vkp, instance, *device);
2126 		vk::SimpleAllocator				alloc		(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2127 		const vk::VkQueue				queue		(getQueue(vkd, *device, queueFamilyIndex));
2128 		const vk::Unique<vk::VkFence>	fence		(createExportableFence(vkd, *device, config.externalType));
2129 		NativeHandle					handleA;
2130 
2131 		if (transference == TRANSFERENCE_COPY)
2132 		{
2133 			submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA);
2134 			if (handleA.hasValidFd() && handleA.getFd() == -1)
2135 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2136 		}
2137 		else
2138 			getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2139 
2140 		{
2141 			NativeHandle					handleB	(handleA);
2142 			const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2143 			const vk::Unique<vk::VkFence>	fenceA	(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2144 			const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2145 
2146 			if (transference == TRANSFERENCE_COPY)
2147 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2148 			else if (transference == TRANSFERENCE_REFERENCE)
2149 			{
2150 				submitEmptySignal(vkd, queue, *fenceA);
2151 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2152 			}
2153 			else
2154 				DE_FATAL("Unknown transference.");
2155 
2156 			VK_CHECK(vkd.queueWaitIdle(queue));
2157 		}
2158 
2159 		return tcu::TestStatus::pass("Pass");
2160 	}
2161 }
2162 
testFenceImportReimport(Context & context,const FenceTestConfig config)2163 tcu::TestStatus testFenceImportReimport (Context&				context,
2164 										 const FenceTestConfig	config)
2165 {
2166 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2167 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2168 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2169 	const vk::InstanceDriver&			vki					(instance.getDriver());
2170 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2171 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2172 
2173 	checkFenceSupport(vki, physicalDevice, config.externalType);
2174 
2175 	{
2176 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2177 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2178 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2179 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2180 
2181 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2182 		NativeHandle					handleA;
2183 
2184 		if (transference == TRANSFERENCE_COPY)
2185 		{
2186 			submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2187 			if (handleA.hasValidFd() && handleA.getFd() == -1)
2188 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2189 		}
2190 		else
2191 			getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2192 
2193 		NativeHandle					handleB	(handleA);
2194 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2195 		const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2196 
2197 		importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2198 
2199 		if (transference == TRANSFERENCE_COPY)
2200 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2201 		else if (transference == TRANSFERENCE_REFERENCE)
2202 		{
2203 			submitEmptySignal(vkd, queue, *fenceA);
2204 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2205 		}
2206 		else
2207 			DE_FATAL("Unknown transference.");
2208 
2209 		VK_CHECK(vkd.queueWaitIdle(queue));
2210 
2211 		return tcu::TestStatus::pass("Pass");
2212 	}
2213 }
2214 
testFenceSignalExportImportWait(Context & context,const FenceTestConfig config)2215 tcu::TestStatus testFenceSignalExportImportWait (Context&				context,
2216 												 const FenceTestConfig	config)
2217 {
2218 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2219 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2220 	const vk::InstanceDriver&			vki					(instance.getDriver());
2221 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2222 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2223 
2224 	checkFenceSupport(vki, physicalDevice, config.externalType);
2225 
2226 	{
2227 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2228 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2229 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2230 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2231 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2232 
2233 		{
2234 			NativeHandle	handle;
2235 
2236 			submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2237 			if (handle.hasValidFd() && handle.getFd() == -1)
2238 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2239 
2240 			{
2241 				const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2242 				const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2243 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2244 
2245 				VK_CHECK(vkd.queueWaitIdle(queue));
2246 			}
2247 		}
2248 
2249 		return tcu::TestStatus::pass("Pass");
2250 	}
2251 }
2252 
testFenceImportSyncFdSignaled(Context & context,const FenceTestConfig config)2253 tcu::TestStatus testFenceImportSyncFdSignaled (Context&					context,
2254 											   const FenceTestConfig	config)
2255 {
2256 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2257 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2258 	const vk::InstanceDriver&			vki					(instance.getDriver());
2259 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2260 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2261 	const vk::VkFenceImportFlags		flags				= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2262 
2263 	checkFenceSupport(vki, physicalDevice, config.externalType);
2264 
2265 	{
2266 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2267 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2268 		NativeHandle					handle	= -1;
2269 		const vk::Unique<vk::VkFence>	fence	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2270 
2271 		if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2272 			return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2273 
2274 		return tcu::TestStatus::pass("Pass");
2275 	}
2276 }
2277 
testFenceExportSignalImportWait(Context & context,const FenceTestConfig config)2278 tcu::TestStatus testFenceExportSignalImportWait (Context&				context,
2279 												 const FenceTestConfig	config)
2280 {
2281 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2282 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2283 	const vk::InstanceDriver&			vki					(instance.getDriver());
2284 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2285 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2286 	const vk::VkFenceImportFlags		flags				= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2287 
2288 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2289 	checkFenceSupport(vki, physicalDevice, config.externalType);
2290 
2291 	{
2292 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2293 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2294 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2295 
2296 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2297 		NativeHandle					handle;
2298 
2299 		getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2300 
2301 		submitEmptySignal(vkd, queue, *fenceA);
2302 		{
2303 			{
2304 				const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2305 
2306 				VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2307 				VK_CHECK(vkd.queueWaitIdle(queue));
2308 			}
2309 		}
2310 
2311 		return tcu::TestStatus::pass("Pass");
2312 	}
2313 }
2314 
testFenceExportImportSignalWait(Context & context,const FenceTestConfig config)2315 tcu::TestStatus testFenceExportImportSignalWait (Context&				context,
2316 												 const FenceTestConfig	config)
2317 {
2318 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2319 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2320 	const vk::InstanceDriver&			vki					(instance.getDriver());
2321 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2322 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2323 
2324 	DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2325 	checkFenceSupport(vki, physicalDevice, config.externalType);
2326 
2327 	{
2328 		const vk::VkFenceImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2329 		const vk::Unique<vk::VkDevice>	device		(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2330 		const vk::DeviceDriver			vkd			(vkp, instance, *device);
2331 		const vk::VkQueue				queue		(getQueue(vkd, *device, queueFamilyIndex));
2332 
2333 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2334 		NativeHandle					handle;
2335 
2336 		getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2337 
2338 		const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2339 
2340 		submitEmptySignal(vkd, queue, *fenceA);
2341 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2342 
2343 		VK_CHECK(vkd.queueWaitIdle(queue));
2344 
2345 		return tcu::TestStatus::pass("Pass");
2346 	}
2347 }
2348 
testFenceSignalImport(Context & context,const FenceTestConfig config)2349 tcu::TestStatus testFenceSignalImport (Context&					context,
2350 									   const FenceTestConfig	config)
2351 {
2352 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2353 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2354 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2355 	const vk::InstanceDriver&			vki					(instance.getDriver());
2356 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2357 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2358 
2359 	checkFenceSupport(vki, physicalDevice, config.externalType);
2360 
2361 	{
2362 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2363 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2364 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2365 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2366 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2367 
2368 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2369 		const vk::Unique<vk::VkFence>	fenceB	(createFence(vkd, *device));
2370 		NativeHandle					handle;
2371 
2372 		submitEmptySignal(vkd, queue, *fenceB);
2373 		VK_CHECK(vkd.queueWaitIdle(queue));
2374 
2375 		if (transference == TRANSFERENCE_COPY)
2376 		{
2377 			submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2378 			if (handle.hasValidFd() && handle.getFd() == -1)
2379 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2380 		}
2381 		else
2382 			getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2383 
2384 		importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2385 
2386 		if (transference == TRANSFERENCE_COPY)
2387 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2388 		else if (transference == TRANSFERENCE_REFERENCE)
2389 		{
2390 			submitEmptySignal(vkd, queue, *fenceA);
2391 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2392 		}
2393 		else
2394 			DE_FATAL("Unknown transference.");
2395 
2396 		VK_CHECK(vkd.queueWaitIdle(queue));
2397 
2398 		return tcu::TestStatus::pass("Pass");
2399 	}
2400 }
2401 
testFenceReset(Context & context,const FenceTestConfig config)2402 tcu::TestStatus testFenceReset (Context&				context,
2403 								const FenceTestConfig	config)
2404 {
2405 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2406 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2407 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2408 	const vk::InstanceDriver&			vki					(instance.getDriver());
2409 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2410 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2411 
2412 	checkFenceSupport(vki, physicalDevice, config.externalType);
2413 
2414 	{
2415 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2416 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2417 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2418 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2419 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2420 
2421 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2422 		const vk::Unique<vk::VkFence>	fenceB	(createFence(vkd, *device));
2423 		const vk::Unique<vk::VkFence>	fenceC	(createFence(vkd, *device));
2424 		NativeHandle					handle;
2425 
2426 		submitEmptySignal(vkd, queue, *fenceB);
2427 		VK_CHECK(vkd.queueWaitIdle(queue));
2428 
2429 		submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2430 		if (handle.hasValidFd() && handle.getFd() == -1)
2431 			return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2432 
2433 		NativeHandle					handleB	(handle);
2434 		importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2435 		importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2436 
2437 		VK_CHECK(vkd.queueWaitIdle(queue));
2438 		VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2439 
2440 		if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2441 		{
2442 			// vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2443 			// or fenceB should be separate copy of the payload and not affect fenceC
2444 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2445 
2446 			// vkResetFences() should have restored fenceBs prior state and should be now reset
2447 			// or fenceB should have it's separate payload
2448 			submitEmptySignal(vkd, queue, *fenceB);
2449 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2450 		}
2451 		else if (config.permanence == PERMANENCE_PERMANENT)
2452 		{
2453 			DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2454 
2455 			// Reset fences should have reset all of the fences
2456 			submitEmptySignal(vkd, queue, *fenceC);
2457 
2458 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2459 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2460 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2461 		}
2462 		else
2463 			DE_FATAL("Unknown permanence");
2464 
2465 		VK_CHECK(vkd.queueWaitIdle(queue));
2466 
2467 		return tcu::TestStatus::pass("Pass");
2468 	}
2469 }
2470 
testFenceSignalWaitImport(Context & context,const FenceTestConfig config)2471 tcu::TestStatus testFenceSignalWaitImport (Context&					context,
2472 										   const FenceTestConfig	config)
2473 {
2474 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2475 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2476 	const vk::InstanceDriver&			vki					(instance.getDriver());
2477 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2478 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2479 
2480 	checkFenceSupport(vki, physicalDevice, config.externalType);
2481 
2482 	{
2483 		const vk::VkFenceImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2484 		const vk::Unique<vk::VkDevice>	device		(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2485 		const vk::DeviceDriver			vkd			(vkp, instance, *device);
2486 		const vk::VkQueue				queue		(getQueue(vkd, *device, queueFamilyIndex));
2487 
2488 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2489 		const vk::Unique<vk::VkFence>	fenceB	(createFence(vkd, *device));
2490 		NativeHandle					handle;
2491 
2492 		getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2493 
2494 		submitEmptySignal(vkd, queue, *fenceB);
2495 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2496 
2497 		VK_CHECK(vkd.queueWaitIdle(queue));
2498 
2499 		importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2500 
2501 		submitEmptySignal(vkd, queue, *fenceA);
2502 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2503 
2504 		VK_CHECK(vkd.queueWaitIdle(queue));
2505 
2506 		return tcu::TestStatus::pass("Pass");
2507 	}
2508 }
2509 
testFenceMultipleExports(Context & context,const FenceTestConfig config)2510 tcu::TestStatus testFenceMultipleExports (Context&				context,
2511 										  const FenceTestConfig	config)
2512 {
2513 	const size_t						exportCount			= 1024;
2514 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2515 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2516 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2517 	const vk::InstanceDriver&			vki					(instance.getDriver());
2518 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2519 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2520 
2521 	checkFenceSupport(vki, physicalDevice, config.externalType);
2522 
2523 	{
2524 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2525 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2526 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2527 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2528 		const vk::Unique<vk::VkFence>	fence	(createExportableFence(vkd, *device, config.externalType));
2529 
2530 		for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2531 		{
2532 			NativeHandle handle;
2533 
2534 			// Need to touch watchdog due to how long one iteration takes
2535 			context.getTestContext().touchWatchdog();
2536 
2537 			if (transference == TRANSFERENCE_COPY)
2538 			{
2539 				submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2540 				if (handle.hasValidFd() && handle.getFd() == -1)
2541 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2542 			}
2543 			else
2544 				getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2545 		}
2546 
2547 		submitEmptySignal(vkd, queue, *fence);
2548 		VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2549 
2550 		VK_CHECK(vkd.queueWaitIdle(queue));
2551 	}
2552 
2553 	return tcu::TestStatus::pass("Pass");
2554 }
2555 
testFenceMultipleImports(Context & context,const FenceTestConfig config)2556 tcu::TestStatus testFenceMultipleImports (Context&				context,
2557 										  const FenceTestConfig	config)
2558 {
2559 	const size_t						importCount			= 4 * 1024;
2560 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2561 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2562 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2563 	const vk::InstanceDriver&			vki					(instance.getDriver());
2564 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2565 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2566 
2567 	checkFenceSupport(vki, physicalDevice, config.externalType);
2568 
2569 	{
2570 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2571 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2572 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2573 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2574 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2575 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2576 		NativeHandle					handleA;
2577 
2578 		if (transference == TRANSFERENCE_COPY)
2579 		{
2580 			submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2581 			if (handleA.hasValidFd() && handleA.getFd() == -1)
2582 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2583 		}
2584 		else
2585 			getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2586 
2587 		for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2588 		{
2589 			NativeHandle					handleB		(handleA);
2590 			const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2591 		}
2592 
2593 		if (transference == TRANSFERENCE_COPY)
2594 		{
2595 			importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2596 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2597 		}
2598 		else if (transference == TRANSFERENCE_REFERENCE)
2599 		{
2600 			submitEmptySignal(vkd, queue, *fenceA);
2601 			VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2602 		}
2603 		else
2604 			DE_FATAL("Unknown transference.");
2605 
2606 		VK_CHECK(vkd.queueWaitIdle(queue));
2607 	}
2608 
2609 	return tcu::TestStatus::pass("Pass");
2610 }
2611 
testFenceTransference(Context & context,const FenceTestConfig config)2612 tcu::TestStatus testFenceTransference (Context&					context,
2613 									   const FenceTestConfig	config)
2614 {
2615 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2616 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2617 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2618 	const vk::InstanceDriver&			vki					(instance.getDriver());
2619 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2620 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2621 
2622 	checkFenceSupport(vki, physicalDevice, config.externalType);
2623 
2624 	{
2625 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2626 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2627 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2628 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2629 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2630 
2631 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2632 		NativeHandle					handle;
2633 
2634 		submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2635 		if (handle.hasValidFd() && handle.getFd() == -1)
2636 			return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2637 
2638 		{
2639 			const vk::Unique<vk::VkFence>	fenceB	(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2640 
2641 			if (config.permanence == PERMANENCE_PERMANENT)
2642 			{
2643 				if (transference == TRANSFERENCE_COPY)
2644 				{
2645 					submitEmptySignal(vkd, queue, *fenceA);
2646 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2647 					VK_CHECK(vkd.queueWaitIdle(queue));
2648 
2649 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2650 					submitEmptySignal(vkd, queue, *fenceB);
2651 
2652 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2653 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2654 					VK_CHECK(vkd.queueWaitIdle(queue));
2655 				}
2656 				else if (transference== TRANSFERENCE_REFERENCE)
2657 				{
2658 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2659 					VK_CHECK(vkd.queueWaitIdle(queue));
2660 
2661 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2662 					submitEmptySignal(vkd, queue, *fenceA);
2663 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2664 
2665 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2666 					submitEmptySignal(vkd, queue, *fenceB);
2667 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2668 					VK_CHECK(vkd.queueWaitIdle(queue));
2669 				}
2670 				else
2671 					DE_FATAL("Unknown transference.");
2672 			}
2673 			else if (config.permanence == PERMANENCE_TEMPORARY)
2674 			{
2675 				if (transference == TRANSFERENCE_COPY)
2676 				{
2677 					submitEmptySignal(vkd, queue, *fenceA);
2678 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2679 					VK_CHECK(vkd.queueWaitIdle(queue));
2680 
2681 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2682 					submitEmptySignal(vkd, queue, *fenceB);
2683 
2684 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2685 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2686 					VK_CHECK(vkd.queueWaitIdle(queue));
2687 				}
2688 				else if (transference == TRANSFERENCE_REFERENCE)
2689 				{
2690 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2691 					VK_CHECK(vkd.queueWaitIdle(queue));
2692 
2693 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2694 					VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2695 					submitEmptySignal(vkd, queue, *fenceA);
2696 					submitEmptySignal(vkd, queue, *fenceB);
2697 
2698 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2699 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2700 					VK_CHECK(vkd.queueWaitIdle(queue));
2701 				}
2702 				else
2703 					DE_FATAL("Unknown transference.");
2704 			}
2705 			else
2706 				DE_FATAL("Unknown permanence.");
2707 		}
2708 
2709 		return tcu::TestStatus::pass("Pass");
2710 	}
2711 }
2712 
testFenceFdDup(Context & context,const FenceTestConfig config)2713 tcu::TestStatus testFenceFdDup (Context&				context,
2714 								const FenceTestConfig	config)
2715 {
2716 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2717 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2718 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2719 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2720 	const vk::InstanceDriver&			vki					(instance.getDriver());
2721 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2722 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2723 
2724 	checkFenceSupport(vki, physicalDevice, config.externalType);
2725 
2726 	{
2727 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2728 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2729 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2730 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2731 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2732 
2733 		TestLog&						log		= context.getTestContext().getLog();
2734 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2735 
2736 		{
2737 			NativeHandle		fd;
2738 
2739 			if (transference == TRANSFERENCE_COPY)
2740 			{
2741 				submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2742 				if (fd.getFd() == -1)
2743 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2744 			}
2745 			else
2746 				getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2747 
2748 			NativeHandle		newFd	(dup(fd.getFd()));
2749 
2750 			if (newFd.getFd() < 0)
2751 				log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2752 
2753 			TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2754 
2755 			{
2756 				const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2757 
2758 				if (transference == TRANSFERENCE_COPY)
2759 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2760 				else if (transference == TRANSFERENCE_REFERENCE)
2761 				{
2762 					submitEmptySignal(vkd, queue, *fenceA);
2763 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2764 				}
2765 				else
2766 					DE_FATAL("Unknown permanence.");
2767 
2768 				VK_CHECK(vkd.queueWaitIdle(queue));
2769 			}
2770 		}
2771 
2772 		return tcu::TestStatus::pass("Pass");
2773 	}
2774 #else
2775 	DE_UNREF(context);
2776 	DE_UNREF(config);
2777 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2778 #endif
2779 }
2780 
testFenceFdDup2(Context & context,const FenceTestConfig config)2781 tcu::TestStatus testFenceFdDup2 (Context&				context,
2782 								 const FenceTestConfig	config)
2783 {
2784 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2785 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2786 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2787 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2788 	const vk::InstanceDriver&			vki					(instance.getDriver());
2789 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2790 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2791 
2792 	checkFenceSupport(vki, physicalDevice, config.externalType);
2793 
2794 	{
2795 		const vk::VkFenceImportFlags	flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2796 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2797 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2798 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2799 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2800 
2801 		TestLog&						log		= context.getTestContext().getLog();
2802 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2803 		const vk::Unique<vk::VkFence>	fenceB	(createExportableFence(vkd, *device, config.externalType));
2804 
2805 		{
2806 			NativeHandle		fd, secondFd;
2807 
2808 			if (transference == TRANSFERENCE_COPY)
2809 			{
2810 				submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2811 				submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2812 				if (fd.getFd() == -1 || secondFd.getFd() == -1)
2813 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2814 			}
2815 			else
2816 			{
2817 				getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2818 				getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2819 			}
2820 
2821 			int					newFd		(dup2(fd.getFd(), secondFd.getFd()));
2822 
2823 			if (newFd < 0)
2824 				log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2825 
2826 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2827 
2828 			{
2829 				const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2830 
2831 				if (transference == TRANSFERENCE_COPY)
2832 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2833 				else if (transference == TRANSFERENCE_REFERENCE)
2834 				{
2835 					submitEmptySignal(vkd, queue, *fenceA);
2836 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2837 				}
2838 				else
2839 					DE_FATAL("Unknown permanence.");
2840 
2841 				VK_CHECK(vkd.queueWaitIdle(queue));
2842 			}
2843 		}
2844 
2845 		return tcu::TestStatus::pass("Pass");
2846 	}
2847 #else
2848 	DE_UNREF(context);
2849 	DE_UNREF(config);
2850 	TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2851 #endif
2852 }
2853 
testFenceFdDup3(Context & context,const FenceTestConfig config)2854 tcu::TestStatus testFenceFdDup3 (Context&				context,
2855 								 const FenceTestConfig	config)
2856 {
2857 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2858 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2859 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2860 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2861 	const vk::InstanceDriver&			vki					(instance.getDriver());
2862 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2863 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2864 
2865 	checkFenceSupport(vki, physicalDevice, config.externalType);
2866 
2867 	{
2868 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2869 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2870 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2871 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2872 
2873 		TestLog&						log		= context.getTestContext().getLog();
2874 		const vk::Unique<vk::VkFence>	fenceA	(createExportableFence(vkd, *device, config.externalType));
2875 		const vk::Unique<vk::VkFence>	fenceB	(createExportableFence(vkd, *device, config.externalType));
2876 
2877 		{
2878 			NativeHandle					fd, secondFd;
2879 
2880 			if (transference == TRANSFERENCE_COPY)
2881 			{
2882 				submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2883 				submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2884 				if (fd.getFd() == -1 || secondFd.getFd() == -1)
2885 					return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2886 			}
2887 			else
2888 			{
2889 				getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2890 				getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2891 			}
2892 
2893 			const vk::VkFenceImportFlags	flags		= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2894 			const int						newFd		(dup3(fd.getFd(), secondFd.getFd(), 0));
2895 
2896 			if (newFd < 0)
2897 				log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2898 
2899 			TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2900 
2901 			{
2902 				const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2903 
2904 				if (transference == TRANSFERENCE_COPY)
2905 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2906 				else if (transference == TRANSFERENCE_REFERENCE)
2907 				{
2908 					submitEmptySignal(vkd, queue, *fenceA);
2909 					VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2910 				}
2911 				else
2912 					DE_FATAL("Unknown permanence.");
2913 
2914 				VK_CHECK(vkd.queueWaitIdle(queue));
2915 			}
2916 		}
2917 
2918 		return tcu::TestStatus::pass("Pass");
2919 	}
2920 #else
2921 	DE_UNREF(context);
2922 	DE_UNREF(config);
2923 	TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2924 #endif
2925 }
2926 
testFenceFdSendOverSocket(Context & context,const FenceTestConfig config)2927 tcu::TestStatus testFenceFdSendOverSocket (Context&					context,
2928 										   const FenceTestConfig	config)
2929 {
2930 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2931 	const Transference					transference		(getHandelTypeTransferences(config.externalType));
2932 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
2933 	const CustomInstance				instance			(createTestInstance(context, 0u, 0u, config.externalType));
2934 	const vk::InstanceDriver&			vki					(instance.getDriver());
2935 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2936 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2937 
2938 	checkFenceSupport(vki, physicalDevice, config.externalType);
2939 
2940 	{
2941 		const vk::Unique<vk::VkDevice>	device	(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2942 		const vk::DeviceDriver			vkd		(vkp, instance, *device);
2943 		vk::SimpleAllocator				alloc	(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2944 		const vk::VkQueue				queue	(getQueue(vkd, *device, queueFamilyIndex));
2945 
2946 		TestLog&						log		= context.getTestContext().getLog();
2947 		const vk::Unique<vk::VkFence>	fence	(createExportableFence(vkd, *device, config.externalType));
2948 		NativeHandle					fd;
2949 
2950 		if (transference == TRANSFERENCE_COPY)
2951 		{
2952 			submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd);
2953 			if (fd.getFd() == -1)
2954 				return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2955 		}
2956 		else
2957 			getFenceNative(vkd, *device, *fence, config.externalType, fd);
2958 
2959 		{
2960 			int sv[2];
2961 
2962 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2963 			{
2964 				log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2965 				TCU_FAIL("Failed to create socket pair");
2966 			}
2967 
2968 			{
2969 				const NativeHandle	srcSocket	(sv[0]);
2970 				const NativeHandle	dstSocket	(sv[1]);
2971 				std::string			sendData	("deqp");
2972 
2973 				// Send FD
2974 				{
2975 					const int			fdRaw	(fd.getFd());
2976 					msghdr				msg;
2977 					cmsghdr*			cmsg;
2978 					char				buffer[CMSG_SPACE(sizeof(int))];
2979 					iovec				iov		= { &sendData[0], sendData.length()};
2980 
2981 					deMemset(&msg, 0, sizeof(msg));
2982 
2983 					msg.msg_control		= buffer;
2984 					msg.msg_controllen	= sizeof(buffer);
2985 					msg.msg_iovlen		= 1;
2986 					msg.msg_iov			= &iov;
2987 
2988 					cmsg				= CMSG_FIRSTHDR(&msg);
2989 					cmsg->cmsg_level	= SOL_SOCKET;
2990 					cmsg->cmsg_type		= SCM_RIGHTS;
2991 					cmsg->cmsg_len		= CMSG_LEN(sizeof(int));
2992 
2993 					deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2994 					msg.msg_controllen = cmsg->cmsg_len;
2995 
2996 					if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2997 					{
2998 						log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2999 						TCU_FAIL("Failed to send fd over socket");
3000 					}
3001 				}
3002 
3003 				// Recv FD
3004 				{
3005 					msghdr			msg;
3006 					char			buffer[CMSG_SPACE(sizeof(int))];
3007 					std::string		recvData	(4, '\0');
3008 					iovec			iov			= { &recvData[0], recvData.length() };
3009 
3010 					deMemset(&msg, 0, sizeof(msg));
3011 
3012 					msg.msg_control		= buffer;
3013 					msg.msg_controllen	= sizeof(buffer);
3014 					msg.msg_iovlen		= 1;
3015 					msg.msg_iov			= &iov;
3016 
3017 					const ssize_t	bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3018 
3019 					if (bytes < 0)
3020 					{
3021 						log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3022 						TCU_FAIL("Failed to recv fd over socket");
3023 
3024 					}
3025 					else if (bytes != (ssize_t)sendData.length())
3026 					{
3027 						TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3028 					}
3029 					else
3030 					{
3031 						const vk::VkFenceImportFlags		flags	= config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
3032 						const cmsghdr* const				cmsg	= CMSG_FIRSTHDR(&msg);
3033 						int									newFd_;
3034 						deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3035 						NativeHandle						newFd	(newFd_);
3036 
3037 						TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3038 						TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3039 						TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3040 						TCU_CHECK(recvData == sendData);
3041 						TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3042 
3043 						{
3044 							const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3045 
3046 							if (transference == TRANSFERENCE_COPY)
3047 								VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3048 							else if (transference == TRANSFERENCE_REFERENCE)
3049 							{
3050 								submitEmptySignal(vkd, queue, *newFence);
3051 								VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3052 							}
3053 							else
3054 								DE_FATAL("Unknown permanence.");
3055 
3056 							VK_CHECK(vkd.queueWaitIdle(queue));
3057 						}
3058 					}
3059 				}
3060 			}
3061 		}
3062 	}
3063 
3064 	return tcu::TestStatus::pass("Pass");
3065 #else
3066 	DE_UNREF(context);
3067 	DE_UNREF(config);
3068 	TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3069 #endif
3070 }
3071 
testBufferQueries(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)3072 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3073 {
3074 	const vk::VkBufferCreateFlags		createFlags[]		=
3075 	{
3076 		0u,
3077 		vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3078 		vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3079 		vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
3080 	};
3081 	const vk::VkBufferUsageFlags		usageFlags[]		=
3082 	{
3083 		vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3084 		vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3085 		vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
3086 		vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3087 		vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
3088 		vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3089 		vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
3090 		vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3091 		vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
3092 	};
3093 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3094 	const CustomInstance				instance			(createTestInstance(context, 0u, externalType, 0u));
3095 	const vk::InstanceDriver&			vki					(instance.getDriver());
3096 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3097 	const vk::VkPhysicalDeviceFeatures	deviceFeatures		(vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3098 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3099 
3100 	// VkDevice is only created if physical device claims to support any of these types.
3101 	vk::Move<vk::VkDevice>				device;
3102 	de::MovePtr<vk::DeviceDriver>		vkd;
3103 	bool								deviceHasDedicated	= false;
3104 
3105 	TestLog&							log					= context.getTestContext().getLog();
3106 
3107 	for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3108 	for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3109 	{
3110 		const vk::VkBufferViewCreateFlags				createFlag		= createFlags[createFlagNdx];
3111 		const vk::VkBufferUsageFlags					usageFlag		= usageFlags[usageFlagNdx];
3112 		const vk::VkPhysicalDeviceExternalBufferInfo	info			=
3113 		{
3114 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
3115 			DE_NULL,
3116 			createFlag,
3117 			usageFlag,
3118 			externalType
3119 		};
3120 		vk::VkExternalBufferProperties					properties		=
3121 		{
3122 			vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
3123 			DE_NULL,
3124 			{ 0u, 0u, 0u }
3125 		};
3126 
3127 		if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3128 			(deviceFeatures.sparseBinding == VK_FALSE))
3129 			continue;
3130 
3131 		if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3132 			(deviceFeatures.sparseResidencyAliased == VK_FALSE))
3133 			continue;
3134 
3135 		if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3136 			(deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3137 			continue;
3138 
3139 		vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3140 
3141 		log << TestLog::Message << properties << TestLog::EndMessage;
3142 
3143 		TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3144 		TCU_CHECK(properties.pNext == DE_NULL);
3145 		// \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3146 
3147 		if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3148 		{
3149 			const bool	requiresDedicated	= (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3150 
3151 			if (!device || (requiresDedicated && !deviceHasDedicated))
3152 			{
3153 				// \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3154 				try
3155 				{
3156 					device				= createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3157 					vkd					= de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3158 					deviceHasDedicated	= requiresDedicated;
3159 				}
3160 				catch (const tcu::NotSupportedError& e)
3161 				{
3162 					log << e;
3163 					TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3164 				}
3165 			}
3166 		}
3167 
3168 		if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3169 		{
3170 			DE_ASSERT(!!device);
3171 			DE_ASSERT(vkd);
3172 
3173 			if (deviceHasDedicated)
3174 			{
3175 				const vk::Unique<vk::VkBuffer>				buffer						(createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3176 				const vk::VkMemoryDedicatedRequirements		reqs						(getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3177 				const bool									propertiesRequiresDedicated	= (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3178 				const bool									objectRequiresDedicated		= (reqs.requiresDedicatedAllocation != VK_FALSE);
3179 
3180 				if (propertiesRequiresDedicated != objectRequiresDedicated)
3181 					TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3182 			}
3183 			else
3184 			{
3185 				// We can't query whether dedicated memory is required or not on per-object basis.
3186 				// This check should be redundant as the code above tries to create device with
3187 				// VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3188 				// is required. However, checking again doesn't hurt.
3189 				TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3190 			}
3191 		}
3192 	}
3193 
3194 	return tcu::TestStatus::pass("Pass");
3195 }
3196 
3197 struct MemoryTestConfig
3198 {
MemoryTestConfigvkt::api::__anon90dd3d8b0111::MemoryTestConfig3199 												MemoryTestConfig	(vk::VkExternalMemoryHandleTypeFlagBits	externalType_,
3200 																	 bool										hostVisible_,
3201 																	 bool										dedicated_)
3202 		: externalType	(externalType_)
3203 		, hostVisible	(hostVisible_)
3204 		, dedicated		(dedicated_)
3205 	{
3206 	}
3207 
3208 	vk::VkExternalMemoryHandleTypeFlagBits	externalType;
3209 	bool									hostVisible;
3210 	bool									dedicated;
3211 };
3212 
3213 #if (DE_OS == DE_OS_WIN32)
chooseWin32MemoryType(deUint32 bits)3214 deUint32 chooseWin32MemoryType(deUint32 bits)
3215 {
3216 	if (bits == 0)
3217 		TCU_THROW(NotSupportedError, "No compatible memory type found");
3218 
3219 	return deCtz32(bits);
3220 }
3221 #endif
3222 
testMemoryWin32Create(Context & context,MemoryTestConfig config)3223 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
3224 {
3225 #if (DE_OS == DE_OS_WIN32)
3226 	const vk::PlatformInterface&				vkp					(context.getPlatformInterface());
3227 	const CustomInstance						instance			(createTestInstance(context, 0u, config.externalType, 0u));
3228 	const vk::InstanceDriver&					vki					(instance.getDriver());
3229 	const vk::VkPhysicalDevice					physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3230 	const deUint32								queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3231 	const vk::Unique<vk::VkDevice>				device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3232 	const vk::DeviceDriver						vkd					(vkp, instance, *device);
3233 	const vk::VkBufferUsageFlags				usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3234 	const deUint32								seed				= 1261033864u;
3235 	const vk::VkDeviceSize						bufferSize			= 1024;
3236 	const std::vector<deUint8>					testData			(genTestData(seed, (size_t)bufferSize));
3237 
3238 	const vk::VkPhysicalDeviceMemoryProperties	memoryProps			= vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3239 	const deUint32								compatibleMemTypes	= vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3240 
3241 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3242 
3243 	// \note Buffer is only allocated to get memory requirements
3244 	const vk::Unique<vk::VkBuffer>				buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3245 	const vk::VkMemoryRequirements				requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3246 	const vk::VkExportMemoryWin32HandleInfoKHR	win32Info				=
3247 	{
3248 		vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
3249 		DE_NULL,
3250 
3251 		(vk::pt::Win32SecurityAttributesPtr)DE_NULL,
3252 		DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3253 		(vk::pt::Win32LPCWSTR)DE_NULL
3254 	};
3255 	const vk::VkExportMemoryAllocateInfo		exportInfo			=
3256 	{
3257 		vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
3258 		&win32Info,
3259 		(vk::VkExternalMemoryHandleTypeFlags)config.externalType
3260 	};
3261 
3262 	const deUint32								exportedMemoryTypeIndex	= chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3263 	const vk::VkMemoryAllocateInfo				info					=
3264 	{
3265 		vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
3266 		&exportInfo,
3267 		requirements.size,
3268 		exportedMemoryTypeIndex
3269 	};
3270 	const vk::Unique<vk::VkDeviceMemory>		memory					(vk::allocateMemory(vkd, *device, &info));
3271 	NativeHandle								handleA;
3272 
3273 	if (config.hostVisible)
3274 		writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3275 
3276 	getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3277 
3278 	{
3279 		const vk::Unique<vk::VkDeviceMemory>	memoryA	(importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3280 
3281 		if (config.hostVisible)
3282 		{
3283 			const std::vector<deUint8>		testDataA		(genTestData(seed ^ 124798807u, (size_t)bufferSize));
3284 			const std::vector<deUint8>		testDataB		(genTestData(seed ^ 970834278u, (size_t)bufferSize));
3285 
3286 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3287 			checkHostMemory(vkd, *device, *memory,  testData.size(), &testData[0]);
3288 
3289 			writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3290 			writeHostMemory(vkd, *device, *memory,  testDataA.size(), &testDataB[0]);
3291 
3292 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3293 			checkHostMemory(vkd, *device, *memory,  testData.size(), &testDataB[0]);
3294 		}
3295 	}
3296 
3297 	return tcu::TestStatus::pass("Pass");
3298 #else
3299 	DE_UNREF(context);
3300 	DE_UNREF(config);
3301 	TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3302 #endif
3303 }
3304 
getExportedMemoryTypeIndex(const vk::InstanceDriver & vki,const vk::VkPhysicalDevice physicalDevice,bool hostVisible,deUint32 memoryBits)3305 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3306 {
3307 	if (hostVisible)
3308 	{
3309 		const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3310 		return chooseHostVisibleMemoryType(memoryBits, properties);
3311 	}
3312 
3313 	return chooseMemoryType(memoryBits);
3314 }
3315 
testMemoryImportTwice(Context & context,MemoryTestConfig config)3316 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
3317 {
3318 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3319 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3320 	const vk::InstanceDriver&				vki					(instance.getDriver());
3321 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3322 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3323 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3324 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3325 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3326 	const deUint32							seed				= 1261033864u;
3327 	const vk::VkDeviceSize					bufferSize			= 1024;
3328 	const std::vector<deUint8>				testData			(genTestData(seed, (size_t)bufferSize));
3329 
3330 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3331 
3332 	// \note Buffer is only allocated to get memory requirements
3333 	const vk::Unique<vk::VkBuffer>				buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3334 	const vk::VkMemoryRequirements				requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3335 	deUint32									exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3336 	const vk::Unique<vk::VkDeviceMemory>		memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3337 	NativeHandle								handleA;
3338 
3339 	if (config.hostVisible)
3340 		writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3341 
3342 	getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3343 
3344 	// Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3345 	// Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3346 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3347 	{
3348 		vk::VkAndroidHardwareBufferPropertiesANDROID	ahbProperties	=
3349 		{
3350 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,	// VkStructureType	sType
3351 			DE_NULL,															// void*			pNext
3352 			0u,																	// VkDeviceSize		allocationSize
3353 			0u																	// uint32_t			memoryTypeBits
3354 		};
3355 		vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handleA.getAndroidHardwareBuffer(), &ahbProperties);
3356 
3357 		exportedMemoryTypeIndex	= getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, ahbProperties.memoryTypeBits);
3358 	}
3359 
3360 	{
3361 		const vk::Unique<vk::VkBuffer>			bufferA	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3362 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3363 		NativeHandle							handleB	(handleA);
3364 		const vk::Unique<vk::VkDeviceMemory>	memoryA	(config.dedicated
3365 														 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3366 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3367 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3368 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3369 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3370 
3371 		if (config.hostVisible)
3372 		{
3373 			const std::vector<deUint8>		testDataA		(genTestData(seed ^ 124798807u, (size_t)bufferSize));
3374 			const std::vector<deUint8>		testDataB		(genTestData(seed ^ 970834278u, (size_t)bufferSize));
3375 
3376 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3377 			checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3378 
3379 			writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3380 			writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3381 
3382 			checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3383 			checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3384 		}
3385 	}
3386 
3387 	return tcu::TestStatus::pass("Pass");
3388 }
3389 
testMemoryMultipleImports(Context & context,MemoryTestConfig config)3390 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3391 {
3392 	const size_t							count				= 4 * 1024;
3393 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3394 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3395 	const vk::InstanceDriver&				vki					(instance.getDriver());
3396 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3397 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3398 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3399 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3400 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3401 	const vk::VkDeviceSize					bufferSize			= 1024;
3402 
3403 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3404 
3405 	// \note Buffer is only allocated to get memory requirements
3406 	const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3407 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3408 	deUint32								exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3409 	const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3410 	NativeHandle							handleA;
3411 
3412 	getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3413 
3414 	// Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3415 	// Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3416 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3417 	{
3418 		vk::VkAndroidHardwareBufferPropertiesANDROID	ahbProperties	=
3419 		{
3420 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,	// VkStructureType	sType
3421 			DE_NULL,															// void*			pNext
3422 			0u,																	// VkDeviceSize		allocationSize
3423 			0u																	// uint32_t			memoryTypeBits
3424 		};
3425 		vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handleA.getAndroidHardwareBuffer(), &ahbProperties);
3426 
3427 		exportedMemoryTypeIndex	= getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, ahbProperties.memoryTypeBits);
3428 	}
3429 
3430 	for (size_t ndx = 0; ndx < count; ndx++)
3431 	{
3432 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3433 		NativeHandle							handleB	(handleA);
3434 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3435 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3436 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3437 	}
3438 
3439 	return tcu::TestStatus::pass("Pass");
3440 }
3441 
testMemoryMultipleExports(Context & context,MemoryTestConfig config)3442 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3443 {
3444 	const size_t							count				= 4 * 1024;
3445 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3446 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3447 	const vk::InstanceDriver&				vki					(instance.getDriver());
3448 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3449 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3450 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3451 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3452 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3453 	const vk::VkDeviceSize					bufferSize			= 1024;
3454 
3455 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3456 
3457 	// \note Buffer is only allocated to get memory requirements
3458 	const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3459 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3460 	const deUint32							exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3461 	const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3462 
3463 	for (size_t ndx = 0; ndx < count; ndx++)
3464 	{
3465 		NativeHandle	handle;
3466 		getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3467 	}
3468 
3469 	return tcu::TestStatus::pass("Pass");
3470 }
3471 
testMemoryFdProperties(Context & context,MemoryTestConfig config)3472 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3473 {
3474 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3475 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3476 	const vk::InstanceDriver&				vki					(instance.getDriver());
3477 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3478 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3479 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3480 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3481 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3482 	const vk::VkDeviceSize					bufferSize			= 1024;
3483 
3484 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3485 
3486 	// \note Buffer is only allocated to get memory requirements
3487 	const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3488 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3489 	const deUint32							exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3490 	const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3491 
3492 	vk::VkMemoryFdPropertiesKHR	properties;
3493 	NativeHandle				handle;
3494 
3495 	getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3496 	properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3497 	vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3498 
3499 	switch (config.externalType)
3500 	{
3501 		case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3502 			TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3503 			break;
3504 		default:
3505 			// Invalid external memory type for this test.
3506 			DE_ASSERT(false);
3507 			break;
3508 	}
3509 
3510 	return tcu::TestStatus::pass("Pass");
3511 }
3512 
testMemoryFdDup(Context & context,MemoryTestConfig config)3513 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3514 {
3515 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3516 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3517 	const CustomInstance				instance			(createTestInstance(context, 0u, config.externalType, 0u));
3518 	const vk::InstanceDriver&			vki					(instance.getDriver());
3519 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3520 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3521 
3522 	{
3523 		const vk::Unique<vk::VkDevice>			device			(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3524 		const vk::DeviceDriver					vkd				(vkp, instance, *device);
3525 
3526 		TestLog&								log				= context.getTestContext().getLog();
3527 		const vk::VkBufferUsageFlags			usage			= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3528 		const vk::VkDeviceSize					bufferSize		= 1024;
3529 		const deUint32							seed			= 851493858u;
3530 		const std::vector<deUint8>				testData		(genTestData(seed, (size_t)bufferSize));
3531 
3532 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3533 
3534 		// \note Buffer is only allocated to get memory requirements
3535 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3536 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3537 		const deUint32							exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3538 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3539 
3540 		if (config.hostVisible)
3541 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3542 
3543 		const NativeHandle						fd				(getMemoryFd(vkd, *device, *memory, config.externalType));
3544 		NativeHandle							newFd			(dup(fd.getFd()));
3545 
3546 		if (newFd.getFd() < 0)
3547 			log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3548 
3549 		TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3550 
3551 		{
3552 			const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3553 			const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3554 																 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3555 																 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3556 
3557 			if (config.hostVisible)
3558 			{
3559 				const std::vector<deUint8>	testDataA	(genTestData(seed ^ 672929437u, (size_t)bufferSize));
3560 
3561 				checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3562 
3563 				writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3564 				checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3565 			}
3566 		}
3567 
3568 		return tcu::TestStatus::pass("Pass");
3569 	}
3570 #else
3571 	DE_UNREF(context);
3572 	DE_UNREF(config);
3573 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3574 #endif
3575 }
3576 
testMemoryFdDup2(Context & context,MemoryTestConfig config)3577 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3578 {
3579 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3580 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3581 	const CustomInstance				instance			(createTestInstance(context, 0u, config.externalType, 0u));
3582 	const vk::InstanceDriver&			vki					(instance.getDriver());
3583 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3584 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3585 
3586 	{
3587 		const vk::Unique<vk::VkDevice>			device			(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3588 		const vk::DeviceDriver					vkd				(vkp, instance, *device);
3589 
3590 		TestLog&								log				= context.getTestContext().getLog();
3591 		const vk::VkBufferUsageFlags			usage			= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3592 		const vk::VkDeviceSize					bufferSize		= 1024;
3593 		const deUint32							seed			= 224466865u;
3594 		const std::vector<deUint8>				testData		(genTestData(seed, (size_t)bufferSize));
3595 
3596 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3597 
3598 		// \note Buffer is only allocated to get memory requirements
3599 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3600 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3601 		const deUint32							exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3602 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3603 
3604 		if (config.hostVisible)
3605 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3606 
3607 		const NativeHandle						fd				(getMemoryFd(vkd, *device, *memory, config.externalType));
3608 		NativeHandle							secondFd		(getMemoryFd(vkd, *device, *memory, config.externalType));
3609 		const int								newFd			(dup2(fd.getFd(), secondFd.getFd()));
3610 
3611 		if (newFd < 0)
3612 			log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3613 
3614 		TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3615 
3616 		{
3617 			const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3618 			const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3619 																 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3620 																 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3621 
3622 			if (config.hostVisible)
3623 			{
3624 				const std::vector<deUint8>	testDataA	(genTestData(seed ^ 99012346u, (size_t)bufferSize));
3625 
3626 				checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3627 
3628 				writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3629 				checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3630 			}
3631 		}
3632 
3633 		return tcu::TestStatus::pass("Pass");
3634 	}
3635 #else
3636 	DE_UNREF(context);
3637 	DE_UNREF(config);
3638 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3639 #endif
3640 }
3641 
testMemoryFdDup3(Context & context,MemoryTestConfig config)3642 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3643 {
3644 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3645 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
3646 	const CustomInstance				instance			(createTestInstance(context, 0u, config.externalType, 0u));
3647 	const vk::InstanceDriver&			vki					(instance.getDriver());
3648 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3649 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3650 
3651 	{
3652 		const vk::Unique<vk::VkDevice>			device			(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3653 		const vk::DeviceDriver					vkd				(vkp, instance, *device);
3654 
3655 		TestLog&								log				= context.getTestContext().getLog();
3656 		const vk::VkBufferUsageFlags			usage			= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3657 		const vk::VkDeviceSize					bufferSize		= 1024;
3658 		const deUint32							seed			= 2554088961u;
3659 		const std::vector<deUint8>				testData		(genTestData(seed, (size_t)bufferSize));
3660 
3661 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3662 
3663 		// \note Buffer is only allocated to get memory requirements
3664 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3665 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3666 		const deUint32							exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3667 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3668 
3669 		if (config.hostVisible)
3670 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3671 
3672 		const NativeHandle						fd				(getMemoryFd(vkd, *device, *memory, config.externalType));
3673 		NativeHandle							secondFd		(getMemoryFd(vkd, *device, *memory, config.externalType));
3674 		const int								newFd			(dup3(fd.getFd(), secondFd.getFd(), 0));
3675 
3676 		if (newFd < 0)
3677 			log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3678 
3679 		TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3680 
3681 		{
3682 			const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3683 			const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3684 																 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3685 																 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3686 
3687 			if (config.hostVisible)
3688 			{
3689 				const std::vector<deUint8>	testDataA	(genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3690 
3691 				checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3692 
3693 				writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3694 				checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3695 			}
3696 		}
3697 
3698 		return tcu::TestStatus::pass("Pass");
3699 	}
3700 #else
3701 	DE_UNREF(context);
3702 	DE_UNREF(config);
3703 	TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3704 #endif
3705 }
3706 
testMemoryFdSendOverSocket(Context & context,MemoryTestConfig config)3707 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3708 {
3709 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3710 	const vk::PlatformInterface&				vkp					(context.getPlatformInterface());
3711 	const CustomInstance						instance			(createTestInstance(context, 0u, config.externalType, 0u));
3712 	const vk::InstanceDriver&					vki					(instance.getDriver());
3713 	const vk::VkPhysicalDevice					physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3714 	const deUint32								queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3715 
3716 	{
3717 		const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3718 		const vk::DeviceDriver					vkd					(vkp, instance, *device);
3719 
3720 		TestLog&								log					= context.getTestContext().getLog();
3721 		const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3722 		const vk::VkDeviceSize					bufferSize			= 1024;
3723 		const deUint32							seed				= 3403586456u;
3724 		const std::vector<deUint8>				testData			(genTestData(seed, (size_t)bufferSize));
3725 
3726 		checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3727 
3728 		// \note Buffer is only allocated to get memory requirements
3729 		const vk::Unique<vk::VkBuffer>			buffer					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3730 		const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *buffer));
3731 		const deUint32							exportedMemoryTypeIndex	(getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3732 		const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3733 
3734 		if (config.hostVisible)
3735 			writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3736 
3737 		const NativeHandle						fd					(getMemoryFd(vkd, *device, *memory, config.externalType));
3738 
3739 		{
3740 			int sv[2];
3741 
3742 			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3743 			{
3744 				log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3745 				TCU_FAIL("Failed to create socket pair");
3746 			}
3747 
3748 			{
3749 				const NativeHandle	srcSocket	(sv[0]);
3750 				const NativeHandle	dstSocket	(sv[1]);
3751 				std::string			sendData	("deqp");
3752 
3753 				// Send FD
3754 				{
3755 					const int			fdRaw	(fd.getFd());
3756 					msghdr				msg;
3757 					cmsghdr*			cmsg;
3758 					char				tmpBuffer[CMSG_SPACE(sizeof(int))];
3759 					iovec				iov		= { &sendData[0], sendData.length()};
3760 
3761 					deMemset(&msg, 0, sizeof(msg));
3762 
3763 					msg.msg_control		= tmpBuffer;
3764 					msg.msg_controllen	= sizeof(tmpBuffer);
3765 					msg.msg_iovlen		= 1;
3766 					msg.msg_iov			= &iov;
3767 
3768 					cmsg				= CMSG_FIRSTHDR(&msg);
3769 					cmsg->cmsg_level	= SOL_SOCKET;
3770 					cmsg->cmsg_type		= SCM_RIGHTS;
3771 					cmsg->cmsg_len		= CMSG_LEN(sizeof(int));
3772 
3773 					deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3774 					msg.msg_controllen = cmsg->cmsg_len;
3775 
3776 					if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3777 					{
3778 						log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3779 						TCU_FAIL("Failed to send fd over socket");
3780 					}
3781 				}
3782 
3783 				// Recv FD
3784 				{
3785 					msghdr			msg;
3786 					char			tmpBuffer[CMSG_SPACE(sizeof(int))];
3787 					std::string		recvData	(4, '\0');
3788 					iovec			iov			= { &recvData[0], recvData.length() };
3789 
3790 					deMemset(&msg, 0, sizeof(msg));
3791 
3792 					msg.msg_control		= tmpBuffer;
3793 					msg.msg_controllen	= sizeof(tmpBuffer);
3794 					msg.msg_iovlen		= 1;
3795 					msg.msg_iov			= &iov;
3796 
3797 					const ssize_t	bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3798 
3799 					if (bytes < 0)
3800 					{
3801 						log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3802 						TCU_FAIL("Failed to recv fd over socket");
3803 
3804 					}
3805 					else if (bytes != (ssize_t)sendData.length())
3806 					{
3807 						TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3808 					}
3809 					else
3810 					{
3811 						const cmsghdr* const	cmsg	= CMSG_FIRSTHDR(&msg);
3812 						int						newFd_;
3813 						deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3814 						NativeHandle			newFd	(newFd_);
3815 
3816 						TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3817 						TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3818 						TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3819 						TCU_CHECK(recvData == sendData);
3820 						TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3821 
3822 						{
3823 							const vk::Unique<vk::VkBuffer>			newBuffer	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3824 							const vk::Unique<vk::VkDeviceMemory>	newMemory	(config.dedicated
3825 																				 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3826 																				 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3827 
3828 							if (config.hostVisible)
3829 							{
3830 								const std::vector<deUint8>	testDataA	(genTestData(seed ^ 23478978u, (size_t)bufferSize));
3831 
3832 								checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3833 
3834 								writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3835 								checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3836 							}
3837 						}
3838 					}
3839 				}
3840 			}
3841 		}
3842 	}
3843 
3844 	return tcu::TestStatus::pass("Pass");
3845 #else
3846 	DE_UNREF(context);
3847 	DE_UNREF(config);
3848 	TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3849 #endif
3850 }
3851 
3852 struct BufferTestConfig
3853 {
BufferTestConfigvkt::api::__anon90dd3d8b0111::BufferTestConfig3854 											BufferTestConfig	(vk::VkExternalMemoryHandleTypeFlagBits		externalType_,
3855 																 bool										dedicated_)
3856 		: externalType	(externalType_)
3857 		, dedicated		(dedicated_)
3858 	{
3859 	}
3860 
3861 	vk::VkExternalMemoryHandleTypeFlagBits	externalType;
3862 	bool									dedicated;
3863 };
3864 
testBufferBindExportImportBind(Context & context,const BufferTestConfig config)3865 tcu::TestStatus testBufferBindExportImportBind (Context&				context,
3866 												const BufferTestConfig	config)
3867 {
3868 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3869 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3870 	const vk::InstanceDriver&				vki					(instance.getDriver());
3871 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3872 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3873 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3874 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3875 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3876 	const vk::VkDeviceSize					bufferSize			= 1024;
3877 
3878 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3879 
3880 	// \note Buffer is only allocated to get memory requirements
3881 	const vk::Unique<vk::VkBuffer>			bufferA					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3882 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *bufferA));
3883 	deUint32								exportedMemoryTypeIndex	(chooseMemoryType(requirements.memoryTypeBits));
3884 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3885 	NativeHandle							handle;
3886 
3887 	VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3888 
3889 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3890 
3891 	// Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3892 	// Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3893 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3894 	{
3895 		vk::VkAndroidHardwareBufferPropertiesANDROID	ahbProperties	=
3896 		{
3897 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,	// VkStructureType	sType
3898 			DE_NULL,															// void*			pNext
3899 			0u,																	// VkDeviceSize		allocationSize
3900 			0u																	// uint32_t			memoryTypeBits
3901 		};
3902 		vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handle.getAndroidHardwareBuffer(), &ahbProperties);
3903 
3904 		exportedMemoryTypeIndex	= chooseMemoryType(ahbProperties.memoryTypeBits);
3905 	}
3906 
3907 	{
3908 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3909 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3910 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3911 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3912 
3913 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3914 	}
3915 
3916 	return tcu::TestStatus::pass("Pass");
3917 }
3918 
testBufferExportBindImportBind(Context & context,const BufferTestConfig config)3919 tcu::TestStatus testBufferExportBindImportBind (Context&				context,
3920 												const BufferTestConfig	config)
3921 {
3922 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3923 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3924 	const vk::InstanceDriver&				vki					(instance.getDriver());
3925 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3926 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3927 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3928 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3929 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3930 	const vk::VkDeviceSize					bufferSize			= 1024;
3931 
3932 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3933 
3934 	// \note Buffer is only allocated to get memory requirements
3935 	const vk::Unique<vk::VkBuffer>			bufferA					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3936 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *bufferA));
3937 	deUint32								exportedMemoryTypeIndex	(chooseMemoryType(requirements.memoryTypeBits));
3938 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3939 	NativeHandle							handle;
3940 
3941 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3942 	VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3943 
3944 	// Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3945 	// Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3946 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3947 	{
3948 		vk::VkAndroidHardwareBufferPropertiesANDROID	ahbProperties	=
3949 		{
3950 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,	// VkStructureType	sType
3951 			DE_NULL,															// void*			pNext
3952 			0u,																	// VkDeviceSize		allocationSize
3953 			0u																	// uint32_t			memoryTypeBits
3954 		};
3955 		vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handle.getAndroidHardwareBuffer(), &ahbProperties);
3956 
3957 		exportedMemoryTypeIndex	= chooseMemoryType(ahbProperties.memoryTypeBits);
3958 	}
3959 
3960 	{
3961 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3962 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
3963 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3964 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3965 
3966 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3967 	}
3968 
3969 	return tcu::TestStatus::pass("Pass");
3970 }
3971 
testBufferExportImportBindBind(Context & context,const BufferTestConfig config)3972 tcu::TestStatus testBufferExportImportBindBind (Context&				context,
3973 												const BufferTestConfig	config)
3974 {
3975 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
3976 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
3977 	const vk::InstanceDriver&				vki					(instance.getDriver());
3978 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3979 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3980 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3981 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
3982 	const vk::VkBufferUsageFlags			usage				= vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3983 	const vk::VkDeviceSize					bufferSize			= 1024;
3984 
3985 	checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3986 
3987 	// \note Buffer is only allocated to get memory requirements
3988 	const vk::Unique<vk::VkBuffer>			bufferA					(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3989 	const vk::VkMemoryRequirements			requirements			(getBufferMemoryRequirements(vkd, *device, *bufferA));
3990 	deUint32								exportedMemoryTypeIndex	(chooseMemoryType(requirements.memoryTypeBits));
3991 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3992 	NativeHandle							handle;
3993 
3994 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3995 
3996 	// Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3997 	// Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3998 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3999 	{
4000 		vk::VkAndroidHardwareBufferPropertiesANDROID	ahbProperties	=
4001 		{
4002 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,	// VkStructureType	sType
4003 			DE_NULL,															// void*			pNext
4004 			0u,																	// VkDeviceSize		allocationSize
4005 			0u																	// uint32_t			memoryTypeBits
4006 		};
4007 		vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handle.getAndroidHardwareBuffer(), &ahbProperties);
4008 
4009 		exportedMemoryTypeIndex	= chooseMemoryType(ahbProperties.memoryTypeBits);
4010 	}
4011 
4012 	{
4013 		const vk::Unique<vk::VkBuffer>			bufferB	(createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4014 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
4015 														 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
4016 														 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
4017 
4018 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
4019 		VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
4020 	}
4021 
4022 	return tcu::TestStatus::pass("Pass");
4023 }
4024 
testImageQueries(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)4025 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4026 {
4027 	const vk::VkImageCreateFlags		createFlags[]		=
4028 	{
4029 		0u,
4030 		vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
4031 		vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
4032 		vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
4033 		vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4034 		vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
4035 	};
4036 	const vk::VkImageUsageFlags			usageFlags[]		=
4037 	{
4038 		vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4039 		vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4040 		vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4041 		vk::VK_IMAGE_USAGE_STORAGE_BIT,
4042 		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4043 		vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
4044 		vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4045 		vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
4046 		vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4047 		vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
4048 	};
4049 	const vk::PlatformInterface&		vkp					(context.getPlatformInterface());
4050 	const CustomInstance				instance			(createTestInstance(context, 0u, externalType, 0u));
4051 	const vk::InstanceDriver&			vki					(instance.getDriver());
4052 	const vk::VkPhysicalDevice			physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4053 	const vk::VkPhysicalDeviceFeatures	deviceFeatures		(vk::getPhysicalDeviceFeatures(vki, physicalDevice));
4054 	const deUint32						queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4055 
4056 	// VkDevice is only created if physical device claims to support any of these types.
4057 	vk::Move<vk::VkDevice>				device;
4058 	de::MovePtr<vk::DeviceDriver>		vkd;
4059 	bool								deviceHasDedicated	= false;
4060 
4061 	TestLog&							log					= context.getTestContext().getLog();
4062 
4063 	for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
4064 	for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
4065 	{
4066 		const vk::VkImageViewCreateFlags						createFlag		= createFlags[createFlagNdx];
4067 		const vk::VkImageUsageFlags								usageFlag		= usageFlags[usageFlagNdx];
4068 		const vk::VkFormat										format			=
4069 				(usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
4070 		const vk::VkImageType									type			= vk::VK_IMAGE_TYPE_2D;
4071 		const vk::VkImageTiling									tiling			= vk::VK_IMAGE_TILING_OPTIMAL;
4072 		const vk::VkPhysicalDeviceExternalImageFormatInfo		externalInfo	=
4073 		{
4074 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4075 			DE_NULL,
4076 			externalType
4077 		};
4078 		const vk::VkPhysicalDeviceImageFormatInfo2				info			=
4079 		{
4080 			vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4081 			&externalInfo,
4082 
4083 			format,
4084 			type,
4085 			tiling,
4086 			usageFlag,
4087 			createFlag,
4088 		};
4089 		vk::VkExternalImageFormatProperties						externalProperties	=
4090 		{
4091 			vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4092 			DE_NULL,
4093 			{ 0u, 0u, 0u }
4094 		};
4095 		vk::VkImageFormatProperties2							properties			=
4096 		{
4097 			vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4098 			&externalProperties,
4099 			{
4100 				{ 0u, 0u, 0u },
4101 				0u,
4102 				0u,
4103 				0u,
4104 				0u
4105 			}
4106 		};
4107 
4108 		if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4109 			(deviceFeatures.sparseBinding == VK_FALSE))
4110 			continue;
4111 
4112 		if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4113 			(deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4114 			continue;
4115 
4116 		if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4117 			(deviceFeatures.sparseResidencyAliased == VK_FALSE))
4118 			continue;
4119 
4120 		if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
4121 			continue;
4122 		}
4123 
4124 		log << TestLog::Message << externalProperties << TestLog::EndMessage;
4125 		TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4126 		TCU_CHECK(externalProperties.pNext == DE_NULL);
4127 		// \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4128 
4129 		if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4130 		{
4131 			const bool	requiresDedicated	= (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4132 
4133 			if (!device || (requiresDedicated && !deviceHasDedicated))
4134 			{
4135 				// \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4136 				try
4137 				{
4138 					device				= createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
4139 					vkd					= de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
4140 					deviceHasDedicated	= requiresDedicated;
4141 				}
4142 				catch (const tcu::NotSupportedError& e)
4143 				{
4144 					log << e;
4145 					TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
4146 				}
4147 			}
4148 		}
4149 
4150 		if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4151 		{
4152 			DE_ASSERT(!!device);
4153 			DE_ASSERT(vkd);
4154 
4155 			if (deviceHasDedicated)
4156 			{
4157 				// Memory requirements cannot be queried without binding the image.
4158 				if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4159 					continue;
4160 
4161 				const vk::Unique<vk::VkImage>				image						(createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
4162 				const vk::VkMemoryDedicatedRequirements		reqs						(getMemoryDedicatedRequirements(*vkd, *device, *image));
4163 				const bool									propertiesRequiresDedicated	= (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4164 				const bool									objectRequiresDedicated		= (reqs.requiresDedicatedAllocation != VK_FALSE);
4165 
4166 				if (propertiesRequiresDedicated != objectRequiresDedicated)
4167 					TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
4168 			}
4169 			else
4170 			{
4171 				// We can't query whether dedicated memory is required or not on per-object basis.
4172 				// This check should be redundant as the code above tries to create device with
4173 				// VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4174 				// is required. However, checking again doesn't hurt.
4175 				TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4176 			}
4177 		}
4178 	}
4179 
4180 	return tcu::TestStatus::pass("Pass");
4181 }
4182 
4183 struct ImageTestConfig
4184 {
ImageTestConfigvkt::api::__anon90dd3d8b0111::ImageTestConfig4185 											ImageTestConfig	(vk::VkExternalMemoryHandleTypeFlagBits		externalType_,
4186 															 bool										dedicated_)
4187 		: externalType	(externalType_)
4188 		, dedicated		(dedicated_)
4189 	{
4190 	}
4191 
4192 	vk::VkExternalMemoryHandleTypeFlagBits	externalType;
4193 	bool									dedicated;
4194 };
4195 
testImageBindExportImportBind(Context & context,const ImageTestConfig config)4196 tcu::TestStatus testImageBindExportImportBind (Context&					context,
4197 											   const ImageTestConfig	config)
4198 {
4199 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
4200 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
4201 	const vk::InstanceDriver&				vki					(instance.getDriver());
4202 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4203 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4204 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4205 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
4206 	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);
4207 	const vk::VkFormat						format				= vk::VK_FORMAT_R8G8B8A8_UNORM;
4208 	const deUint32							width				= 64u;
4209 	const deUint32							height				= 64u;
4210 	const vk::VkImageTiling					tiling				= vk::VK_IMAGE_TILING_OPTIMAL;
4211 
4212 	checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4213 
4214 	const vk::Unique<vk::VkImage>			imageA					(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4215 	const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4216 	const deUint32							exportedMemoryTypeIndex	(chooseMemoryType(requirements.memoryTypeBits));
4217 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4218 	NativeHandle							handle;
4219 
4220 	VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4221 
4222 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4223 
4224 	{
4225 		const vk::Unique<vk::VkImage>			imageB	(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4226 		const deUint32							idx		= config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4227 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
4228 														 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4229 														 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4230 
4231 		VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4232 	}
4233 
4234 	return tcu::TestStatus::pass("Pass");
4235 }
4236 
testImageExportBindImportBind(Context & context,const ImageTestConfig config)4237 tcu::TestStatus testImageExportBindImportBind (Context&					context,
4238 											   const ImageTestConfig	config)
4239 {
4240 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
4241 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
4242 	const vk::InstanceDriver&				vki					(instance.getDriver());
4243 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4244 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4245 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4246 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
4247 	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);
4248 	const vk::VkFormat						format				= vk::VK_FORMAT_R8G8B8A8_UNORM;
4249 	const deUint32							width				= 64u;
4250 	const deUint32							height				= 64u;
4251 	const vk::VkImageTiling					tiling				= vk::VK_IMAGE_TILING_OPTIMAL;
4252 
4253 	checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4254 
4255 	const vk::Unique<vk::VkImage>			imageA					(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4256 	const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4257 	const deUint32							exportedMemoryTypeIndex	(chooseMemoryType(requirements.memoryTypeBits));
4258 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4259 	NativeHandle							handle;
4260 
4261 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4262 	{
4263 		// AHB required the image memory to be bound first.
4264 		VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4265 		getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4266 	}
4267 	else
4268 	{
4269 		getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4270 		VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4271 	}
4272 
4273 	{
4274 		const vk::Unique<vk::VkImage>			imageB	(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4275 		const deUint32							idx		= config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4276 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
4277 														 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4278 														 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4279 
4280 		VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4281 	}
4282 
4283 	return tcu::TestStatus::pass("Pass");
4284 }
4285 
testImageExportImportBindBind(Context & context,const ImageTestConfig config)4286 tcu::TestStatus testImageExportImportBindBind (Context&					context,
4287 											   const ImageTestConfig	config)
4288 {
4289 	const vk::PlatformInterface&			vkp					(context.getPlatformInterface());
4290 	const CustomInstance					instance			(createTestInstance(context, 0u, config.externalType, 0u));
4291 	const vk::InstanceDriver&				vki					(instance.getDriver());
4292 	const vk::VkPhysicalDevice				physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4293 	const deUint32							queueFamilyIndex	(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4294 	const vk::Unique<vk::VkDevice>			device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4295 	const vk::DeviceDriver					vkd					(vkp, instance, *device);
4296 	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);
4297 	const vk::VkFormat						format				= vk::VK_FORMAT_R8G8B8A8_UNORM;
4298 	const deUint32							width				= 64u;
4299 	const deUint32							height				= 64u;
4300 	const vk::VkImageTiling					tiling				= vk::VK_IMAGE_TILING_OPTIMAL;
4301 
4302 	checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4303 
4304 	if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4305 	{
4306 		// AHB required the image memory to be bound first, which is not possible in this test.
4307 		TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4308 	}
4309 
4310 	// \note Image is only allocated to get memory requirements
4311 	const vk::Unique<vk::VkImage>			imageA					(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4312 	const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4313 	const deUint32							exportedMemoryTypeIndex	(chooseMemoryType(requirements.memoryTypeBits));
4314 	const vk::Unique<vk::VkDeviceMemory>	memoryA					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4315 	NativeHandle							handle;
4316 
4317 	getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4318 
4319 	{
4320 		const vk::Unique<vk::VkImage>			imageB	(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4321 		const deUint32							idx		= config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4322 		const vk::Unique<vk::VkDeviceMemory>	memoryB	(config.dedicated
4323 														 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4324 														 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4325 
4326 		VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4327 		VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4328 	}
4329 
4330 	return tcu::TestStatus::pass("Pass");
4331 }
4332 
checkEvent(Context & context,const TestConfig)4333 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
4334 {
4335 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
4336 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4337 }
4338 
checkSupport(Context & context,const TestConfig config)4339 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
4340 {
4341 	const Transference transference (getHandelTypeTransferences(config.externalType));
4342 	if (transference == TRANSFERENCE_COPY)
4343 		checkEvent(context, config);
4344 }
4345 
createFenceTests(tcu::TestContext & testCtx,vk::VkExternalFenceHandleTypeFlagBits externalType)4346 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
4347 {
4348 	const struct
4349 	{
4350 		const char* const	name;
4351 		const Permanence	permanence;
4352 	} permanences[] =
4353 	{
4354 		{ "temporary", PERMANENCE_TEMPORARY	},
4355 		{ "permanent", PERMANENCE_PERMANENT	}
4356 	};
4357 
4358 	de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
4359 
4360 	addFunctionCase(fenceGroup.get(), "info",	"Test external fence queries.",	testFenceQueries,	externalType);
4361 
4362 	for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4363 	{
4364 		const Permanence		permanence		(permanences[permanenceNdx].permanence);
4365 		const char* const		permanenceName	(permanences[permanenceNdx].name);
4366 		const FenceTestConfig	config			(externalType, permanence);
4367 
4368 		if (!isSupportedPermanence(externalType, permanence))
4369 			continue;
4370 
4371 		if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4372 			|| externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4373 		{
4374 			addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName,	"Test creating fence with win32 properties.",	testFenceWin32Create,	config);
4375 		}
4376 
4377 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName,				"Test importing fence twice.",											checkSupport,	initProgramsToGetNativeFd,	testFenceImportTwice,				config);
4378 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName,					"Test importing again over previously imported fence.",					checkSupport,	initProgramsToGetNativeFd,	testFenceImportReimport,			config);
4379 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName,		"Test importing fence multiple times.",									checkSupport,	initProgramsToGetNativeFd,	testFenceMultipleImports,			config);
4380 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName,	"Test signaling, exporting, importing and waiting for the sempahore.",	checkEvent,		initProgramsToGetNativeFd,	testFenceSignalExportImportWait,	config);
4381 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName,				"Test signaling and importing the fence.",								checkSupport,	initProgramsToGetNativeFd,	testFenceSignalImport,				config);
4382 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName,						"Test resetting the fence.",											checkEvent,		initProgramsToGetNativeFd,	testFenceReset,						config);
4383 		addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName,				"Test fences transference.",											checkEvent,		initProgramsToGetNativeFd,	testFenceTransference,				config);
4384 
4385 		if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4386 		{
4387 			addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName,			"Test import signaled fence fd.",										initProgramsToGetNativeFd,	testFenceImportSyncFdSignaled,		config);
4388 		}
4389 
4390 		if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4391 			|| externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4392 		{
4393 			// \note Not supported on WIN32 handles
4394 			addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName,	"Test exporting fence multiple times.",		checkSupport,	initProgramsToGetNativeFd,	testFenceMultipleExports,	config);
4395 
4396 			addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName,						"Test calling dup() on exported fence.",	checkSupport,	initProgramsToGetNativeFd,	testFenceFdDup,				config);
4397 			addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName,					"Test calling dup2() on exported fence.",	checkSupport,	initProgramsToGetNativeFd,	testFenceFdDup2,			config);
4398 			addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName,					"Test calling dup3() on exported fence.",	checkSupport,	initProgramsToGetNativeFd,	testFenceFdDup3,			config);
4399 			addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName,		"Test sending fence fd over socket.",		checkSupport,	initProgramsToGetNativeFd,	testFenceFdSendOverSocket,	config);
4400 		}
4401 
4402 		if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4403 		{
4404 			addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName,			"Test signaling and then waiting for the the sepmahore.",			testFenceSignalWaitImport,			config);
4405 			addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName,	"Test exporting, signaling, importing and waiting for the fence.",	testFenceExportSignalImportWait,	config);
4406 			addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName,	"Test exporting, importing, signaling and waiting for the fence.",	testFenceExportImportSignalWait,	config);
4407 		}
4408 	}
4409 
4410 	return fenceGroup;
4411 }
4412 
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="")4413 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 = "")
4414 {
4415 	std::ostringstream combination;
4416 	combination << "Test failure with combination: ";
4417 	combination << " Format: "		<< getFormatName(format);
4418 	combination << " Usageflags: "	<< vk::getImageUsageFlagsStr(usage);
4419 	combination << " Createflags: "	<< vk::getImageCreateFlagsStr(create);
4420 	combination << " Tiling: "		<< getImageTilingStr(tiling);
4421 	if (width != 0 && height != 0)
4422 		combination << " Size: " << "(" << width << ", " << height << ")";
4423 	if (!exception.empty())
4424 		combination << "Error message: " << exception;
4425 
4426 	log << TestLog::Message << combination.str() << TestLog::EndMessage;
4427 }
4428 
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)4429 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)
4430 {
4431 	DE_UNREF(createFlag);
4432 
4433 	AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4434 
4435 	if (!ahbApi)
4436 	{
4437 		TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4438 	}
4439 
4440 #if (DE_OS == DE_OS_ANDROID)
4441 	// If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4442 	if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4443 		return false;
4444 #endif
4445 
4446 	vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4447 	if (ahb.internal == DE_NULL)
4448 	{
4449 		enableMaxLayerTest = false;
4450 		// try again with layerCount '1'
4451 		ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4452 		if (ahb.internal == DE_NULL)
4453 		{
4454 			return false;
4455 		}
4456 	}
4457 	NativeHandle nativeHandle(ahb);
4458 
4459 	const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4460 	const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4461 
4462 	for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4463 	{
4464 		// Both mappings should be equivalent and work.
4465 		const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4466 
4467 		vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4468 		{
4469 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4470 			DE_NULL,
4471 			vk::VK_FORMAT_UNDEFINED,
4472 			0u,
4473 			0u,
4474 			mapping,
4475 			vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4476 			vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4477 			vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4478 			vk::VK_CHROMA_LOCATION_COSITED_EVEN
4479 		};
4480 
4481 		vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4482 		{
4483 			vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4484 			&formatProperties,
4485 			0u,
4486 			0u
4487 		};
4488 
4489 		try
4490 		{
4491 			VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4492 			TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4493 			TCU_CHECK(formatProperties.format == format);
4494 			TCU_CHECK(formatProperties.externalFormat != 0u);
4495 			TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4496 			TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4497 		}
4498 		catch (const tcu::Exception& exception)
4499 		{
4500 			log << TestLog::Message << "Failure validating Android Hardware Buffer. See error message and combination: " << TestLog::EndMessage;
4501 			generateFailureText(log, format, usageFlag, createFlag, static_cast<vk::VkImageTiling>(0), 0, 0, exception.getMessage());
4502 			return false;
4503 		}
4504 	}
4505 
4506 	return true;
4507 }
4508 
testAndroidHardwareBufferImageFormat(Context & context,vk::VkFormat format)4509 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4510 {
4511 	AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4512 	if (!ahbApi)
4513 	{
4514 		TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4515 	}
4516 
4517 	bool testsFailed = false;
4518 
4519 	const vk::VkExternalMemoryHandleTypeFlagBits  externalMemoryType  =	vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4520 	const vk::PlatformInterface&				  vkp					(context.getPlatformInterface());
4521 	const CustomInstance						  instance				(createTestInstance(context, 0u, externalMemoryType, 0u));
4522 	const vk::InstanceDriver&					  vki					(instance.getDriver());
4523 	const vk::VkPhysicalDevice					  physicalDevice		(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4524 
4525 	vk::VkPhysicalDeviceProtectedMemoryFeatures		protectedFeatures;
4526 	protectedFeatures.sType				= vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4527 	protectedFeatures.pNext				= DE_NULL;
4528 	protectedFeatures.protectedMemory	= VK_FALSE;
4529 
4530 	vk::VkPhysicalDeviceFeatures2					deviceFeatures;
4531 	deviceFeatures.sType		= vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4532 	deviceFeatures.pNext		= &protectedFeatures;
4533 
4534 	vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4535 
4536 	const deUint32								  queueFamilyIndex		(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4537 	const vk::Unique<vk::VkDevice>				  device				(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4538 	const vk::DeviceDriver						  vkd					(vkp, instance, *device);
4539 	TestLog&									  log				  = context.getTestContext().getLog();
4540 	const vk::VkPhysicalDeviceLimits			  limits			  = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4541 
4542 	const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4543 																						   : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4544 
4545 	const vk::VkImageUsageFlagBits				  usageFlags[]		  =
4546 	{
4547 		vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4548 		vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4549 		vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4550 		vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4551 		framebufferUsageFlag,
4552 	};
4553 	const vk::VkImageCreateFlagBits				  createFlags[]		  =
4554 	{
4555 		vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4556 		vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4557 		vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4558 		vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4559 	};
4560 	const vk::VkImageTiling						  tilings[]			  =
4561 	{
4562 		vk::VK_IMAGE_TILING_OPTIMAL,
4563 		vk::VK_IMAGE_TILING_LINEAR,
4564 	};
4565 	deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4566 	const size_t	one							= 1u;
4567 	const size_t	numOfUsageFlags				= DE_LENGTH_OF_ARRAY(usageFlags);
4568 	const size_t	numOfCreateFlags			= DE_LENGTH_OF_ARRAY(createFlags);
4569 	const size_t	numOfFlagCombos				= one << (numOfUsageFlags + numOfCreateFlags);
4570 	const size_t	numOfTilings				= DE_LENGTH_OF_ARRAY(tilings);
4571 
4572 	for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4573 	{
4574 		vk::VkImageUsageFlags	usage				= 0;
4575 		vk::VkImageCreateFlags	createFlag			= 0;
4576 		deUint64				requiredAhbUsage	= 0;
4577 		bool					enableMaxLayerTest	= true;
4578 		for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4579 		{
4580 			if ((combo & (one << usageNdx)) == 0)
4581 				continue;
4582 			usage |= usageFlags[usageNdx];
4583 			requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4584 		}
4585 		for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4586 		{
4587 			const size_t	bit	= numOfUsageFlags + createFlagNdx;
4588 			if ((combo & (one << bit)) == 0)
4589 				continue;
4590 			if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4591 				(protectedFeatures.protectedMemory == VK_FALSE))
4592 				continue;
4593 
4594 			createFlag |= createFlags[createFlagNdx];
4595 			requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4596 		}
4597 
4598 		// Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4599 		if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4600 			continue;
4601 
4602 		// Only test a combination if AHardwareBuffer can be successfully allocated for it.
4603 		if (!ValidateAHardwareBuffer(log, format, requiredAhbUsage, vkd, *device, usage, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4604 			continue;
4605 
4606 		bool foundAnyUsableTiling = false;
4607 		for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4608 		{
4609 			const vk::VkImageTiling tiling = tilings[tilingIndex];
4610 
4611 			const vk::VkPhysicalDeviceExternalImageFormatInfo	externalInfo		=
4612 			{
4613 				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4614 				DE_NULL,
4615 				vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4616 			};
4617 			const vk::VkPhysicalDeviceImageFormatInfo2			info				=
4618 			{
4619 				vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4620 				&externalInfo,
4621 				format,
4622 				vk::VK_IMAGE_TYPE_2D,
4623 				tiling,
4624 				usage,
4625 				createFlag,
4626 			};
4627 
4628 			vk::VkAndroidHardwareBufferUsageANDROID				ahbUsageProperties	=
4629 			{
4630 				vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4631 				DE_NULL,
4632 				0u
4633 			};
4634 			vk::VkExternalImageFormatProperties					externalProperties	=
4635 			{
4636 				vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4637 				&ahbUsageProperties,
4638 				{ 0u, 0u, 0u }
4639 			};
4640 			vk::VkImageFormatProperties2						properties			=
4641 			{
4642 				vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4643 				&externalProperties,
4644 				{
4645 					{ 0u, 0u, 0u },
4646 					0u,
4647 					0u,
4648 					0u,
4649 					0u
4650 				}
4651 			};
4652 
4653 			if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4654 			{
4655 				log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4656 				continue;
4657 			}
4658 
4659 			foundAnyUsableTiling = true;
4660 
4661 			try
4662 			{
4663 				TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4664 				TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4665 				TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4666 				deUint32 maxWidth   = properties.imageFormatProperties.maxExtent.width;
4667 				deUint32 maxHeight  = properties.imageFormatProperties.maxExtent.height;
4668 				TCU_CHECK(maxWidth >= 4096);
4669 				TCU_CHECK(maxHeight >= 4096);
4670 				// Even if not requested, at least one of GPU_* usage flags must be present.
4671 				TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4672 				// The AHB usage flags corresponding to the create and usage flags used in info must be present.
4673 				TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4674 			}
4675 			catch (const tcu::Exception& exception)
4676 			{
4677 				generateFailureText(log, format, usage, createFlag, tiling, 0, 0, exception.getMessage());
4678 				testsFailed = true;
4679 				continue;
4680 			}
4681 
4682 			log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4683 				<< TestLog::EndMessage;
4684 
4685 			struct ImageSize
4686 			{
4687 				deUint32 width;
4688 				deUint32 height;
4689 			};
4690 			ImageSize sizes[] =
4691 			{
4692 				{64u, 64u},
4693 				{1024u, 2096u},
4694 			};
4695 
4696 			deUint32 exportedMemoryTypeIndex = 0;
4697 
4698 			if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4699 			{
4700 				const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4701 
4702 				for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4703 				{
4704 					if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4705 					{
4706 						exportedMemoryTypeIndex = memoryTypeIndex;
4707 						break;
4708 					}
4709 				}
4710 			}
4711 
4712 			for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4713 			{
4714 				try
4715 				{
4716 					const vk::Unique<vk::VkImage>			image					(createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4717 					const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4718 					const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4719 					NativeHandle							handle;
4720 
4721 					VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4722 					getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4723 
4724 					deUint32 ahbFormat = 0;
4725 					deUint64 anhUsage  = 0;
4726 					ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4727 					TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4728 					TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4729 
4730 					// Let watchdog know we're alive
4731 					context.getTestContext().touchWatchdog();
4732 				}
4733 				catch (const tcu::Exception& exception)
4734 				{
4735 					generateFailureText(log, format, usage, createFlag, tiling, sizes[i].width, sizes[i].height, exception.getMessage());
4736 					testsFailed = true;
4737 					continue;
4738 				}
4739 			}
4740 
4741 			if (properties.imageFormatProperties.maxMipLevels >= 7u)
4742 			{
4743 				try
4744 				{
4745 					const vk::Unique<vk::VkImage>			image					(createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4746 					const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4747 					const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4748 					NativeHandle							handle;
4749 
4750 					VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4751 					getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4752 
4753 					deUint32 ahbFormat = 0;
4754 					deUint64 anhUsage  = 0;
4755 					ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4756 					TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4757 					TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4758 				}
4759 				catch (const tcu::Exception& exception)
4760 				{
4761 					generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
4762 					testsFailed = true;
4763 					continue;
4764 				}
4765 			}
4766 
4767 			if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4768 			{
4769 				try
4770 				{
4771 					const vk::Unique<vk::VkImage>			image					(createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4772 					const vk::VkMemoryRequirements			requirements			(getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4773 					const vk::Unique<vk::VkDeviceMemory>	memory					(allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4774 					NativeHandle							handle;
4775 
4776 					VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4777 					getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4778 
4779 					deUint32 ahbFormat = 0;
4780 					deUint64 anhUsage  = 0;
4781 					ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4782 					TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4783 					TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4784 				}
4785 				catch (const tcu::Exception& exception)
4786 				{
4787 					generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
4788 					testsFailed = true;
4789 					continue;
4790 				}
4791 			}
4792 		}
4793 
4794 		if (!foundAnyUsableTiling)
4795 		{
4796 			generateFailureText(log, format, usage, createFlag, static_cast<vk::VkImageTiling>(0));
4797 			testsFailed = true;
4798 			continue;
4799 		}
4800 	}
4801 
4802 	if (testsFailed)
4803 		return tcu::TestStatus::fail("Failure in at least one subtest. Check log for failed tests.");
4804 	else
4805 		return tcu::TestStatus::pass("Pass");
4806 }
4807 
createFenceTests(tcu::TestContext & testCtx)4808 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4809 {
4810 	de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4811 
4812 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4813 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4814 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4815 	fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4816 
4817 	return fenceGroup;
4818 }
4819 
createSemaphoreTests(tcu::TestContext & testCtx,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)4820 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4821 {
4822 	const struct
4823 	{
4824 		const char* const	name;
4825 		const Permanence	permanence;
4826 	} permanences[] =
4827 	{
4828 		{ "temporary", PERMANENCE_TEMPORARY	},
4829 		{ "permanent", PERMANENCE_PERMANENT	}
4830 	};
4831 	const struct
4832 	{
4833 		const char* const	name;
4834 		vk::VkSemaphoreType	type;
4835 	} semaphoreTypes[] =
4836 	{
4837 		{ "binary",		vk::VK_SEMAPHORE_TYPE_BINARY },
4838 		{ "timeline",	vk::VK_SEMAPHORE_TYPE_TIMELINE },
4839 	};
4840 
4841 	de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4842 
4843 	for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4844 	{
4845 		addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4846 						"Test external semaphore queries.",	testSemaphoreQueries,
4847 						TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4848 	}
4849 
4850 	for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4851 	{
4852 		const Permanence			permanence		(permanences[permanenceNdx].permanence);
4853 		const char* const			permanenceName	(permanences[permanenceNdx].name);
4854 		const SemaphoreTestConfig	config			(externalType, permanence);
4855 
4856 		if (!isSupportedPermanence(externalType, permanence))
4857 			continue;
4858 
4859 		if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4860 			|| externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4861 		{
4862 			addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,	"Test creating semaphore with win32 properties.",	testSemaphoreWin32Create,	config);
4863 		}
4864 
4865 		addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName,				"Test importing semaphore twice.",										checkSupport,	initProgramsToGetNativeFd,	testSemaphoreImportTwice,				config);
4866 		addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName,					"Test importing again over previously imported semaphore.",				checkSupport,	initProgramsToGetNativeFd,	testSemaphoreImportReimport,			config);
4867 		addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,		"Test importing semaphore multiple times.",								checkSupport,	initProgramsToGetNativeFd,	testSemaphoreMultipleImports,			config);
4868 		addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,	"Test signaling, exporting, importing and waiting for the sempahore.",	checkEvent,		initProgramsToGetNativeFd,	testSemaphoreSignalExportImportWait,	config);
4869 		addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName,				"Test signaling and importing the semaphore.",							checkSupport,	initProgramsToGetNativeFd,	testSemaphoreSignalImport,				config);
4870 		addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName,				"Test semaphores transference.",										checkEvent,		initProgramsToGetNativeFd,	testSemaphoreTransference,				config);
4871 
4872 		if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4873 		{
4874 			addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName,			"Test import signaled semaphore fd.",										initProgramsToGetNativeFd,	testSemaphoreImportSyncFdSignaled,	config);
4875 		}
4876 
4877 
4878 		if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4879 			|| externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4880 		{
4881 			// \note Not supported on WIN32 handles
4882 			addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,	"Test exporting semaphore multiple times.",		checkSupport,	initProgramsToGetNativeFd,	testSemaphoreMultipleExports,	config);
4883 
4884 			addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName,						"Test calling dup() on exported semaphore.",	checkSupport,	initProgramsToGetNativeFd,	testSemaphoreFdDup,				config);
4885 			addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName,					"Test calling dup2() on exported semaphore.",	checkSupport,	initProgramsToGetNativeFd,	testSemaphoreFdDup2,			config);
4886 			addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName,					"Test calling dup3() on exported semaphore.",	checkSupport,	initProgramsToGetNativeFd,	testSemaphoreFdDup3,			config);
4887 			addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,		"Test sending semaphore fd over socket.",		checkSupport,	initProgramsToGetNativeFd,	testSemaphoreFdSendOverSocket,	config);
4888 		}
4889 
4890 		if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4891 		{
4892 			addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,			"Test signaling and then waiting for the the sepmahore.",				testSemaphoreSignalWaitImport,			config);
4893 			addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,	"Test exporting, signaling, importing and waiting for the semaphore.",	testSemaphoreExportSignalImportWait,	config);
4894 			addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,	"Test exporting, importing, signaling and waiting for the semaphore.",	checkEvent,		testSemaphoreExportImportSignalWait,	config);
4895 		}
4896 	}
4897 
4898 	return semaphoreGroup;
4899 }
4900 
createSemaphoreTests(tcu::TestContext & testCtx)4901 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4902 {
4903 	de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4904 
4905 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4906 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4907 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4908 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4909 	semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA).release());
4910 
4911 	return semaphoreGroup;
4912 }
4913 
createMemoryTests(tcu::TestContext & testCtx,vk::VkExternalMemoryHandleTypeFlagBits externalType)4914 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4915 {
4916 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4917 
4918 	for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4919 	{
4920 		const bool						dedicated		(dedicatedNdx == 1);
4921 		de::MovePtr<tcu::TestCaseGroup>	dedicatedGroup	(new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4922 
4923 		for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4924 		{
4925 			const bool						hostVisible			(hostVisibleNdx == 1);
4926 			de::MovePtr<tcu::TestCaseGroup>	hostVisibleGroup	(new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4927 			const MemoryTestConfig			memoryConfig		(externalType, hostVisible, dedicated);
4928 
4929 			if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4930 				|| externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4931 			{
4932 				addFunctionCase(hostVisibleGroup.get(), "create_win32",	"Test creating memory with win32 properties .",		testMemoryWin32Create,	memoryConfig);
4933 			}
4934 
4935 			addFunctionCase(hostVisibleGroup.get(), "import_twice",				"Test importing memory object twice.",			testMemoryImportTwice,		memoryConfig);
4936 			addFunctionCase(hostVisibleGroup.get(), "import_multiple_times",	"Test importing memory object multiple times.",	testMemoryMultipleImports,	memoryConfig);
4937 
4938 			if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4939 				|| externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4940 			{
4941 				addFunctionCase(hostVisibleGroup.get(), "dup",						"Test calling dup() on exported memory.",	testMemoryFdDup,			memoryConfig);
4942 				addFunctionCase(hostVisibleGroup.get(), "dup2",						"Test calling dup2() on exported memory.",	testMemoryFdDup2,			memoryConfig);
4943 				addFunctionCase(hostVisibleGroup.get(), "dup3",						"Test calling dup3() on exported memory.",	testMemoryFdDup3,			memoryConfig);
4944 				addFunctionCase(hostVisibleGroup.get(), "send_over_socket",			"Test sending memory fd over socket.",		testMemoryFdSendOverSocket,	memoryConfig);
4945 				// \note Not supported on WIN32 handles
4946 				addFunctionCase(hostVisibleGroup.get(), "export_multiple_times",	"Test exporting memory multiple times.",	testMemoryMultipleExports,	memoryConfig);
4947 			}
4948 
4949 			if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4950 			{
4951 				addFunctionCase(hostVisibleGroup.get(), "fd_properties",			"Test obtaining the FD memory properties",	testMemoryFdProperties,		memoryConfig);
4952 			}
4953 
4954 			dedicatedGroup->addChild(hostVisibleGroup.release());
4955 		}
4956 
4957 		{
4958 			de::MovePtr<tcu::TestCaseGroup>	bufferGroup		(new tcu::TestCaseGroup(testCtx, "buffer", ""));
4959 			const BufferTestConfig			bufferConfig	(externalType, dedicated);
4960 
4961 			addFunctionCase(bufferGroup.get(), "info",						"External buffer memory info query.",						testBufferQueries,				externalType);
4962 			addFunctionCase(bufferGroup.get(), "bind_export_import_bind",	"Test binding, exporting, importing and binding buffer.",	testBufferBindExportImportBind,	bufferConfig);
4963 			addFunctionCase(bufferGroup.get(), "export_bind_import_bind",	"Test exporting, binding, importing and binding buffer.",	testBufferExportBindImportBind,	bufferConfig);
4964 			addFunctionCase(bufferGroup.get(), "export_import_bind_bind",	"Test exporting, importing and binding buffer.",			testBufferExportImportBindBind,	bufferConfig);
4965 
4966 			dedicatedGroup->addChild(bufferGroup.release());
4967 		}
4968 
4969 		{
4970 			de::MovePtr<tcu::TestCaseGroup> imageGroup	(new tcu::TestCaseGroup(testCtx, "image", ""));
4971 			const ImageTestConfig			imageConfig	(externalType, dedicated);
4972 
4973 			addFunctionCase(imageGroup.get(), "info",						"External image memory info query.",						testImageQueries,				externalType);
4974 			addFunctionCase(imageGroup.get(), "bind_export_import_bind",	"Test binding, exporting, importing and binding image.",	testImageBindExportImportBind,	imageConfig);
4975 			addFunctionCase(imageGroup.get(), "export_bind_import_bind",	"Test exporting, binding, importing and binding image.",	testImageExportBindImportBind,	imageConfig);
4976 			addFunctionCase(imageGroup.get(), "export_import_bind_bind",	"Test exporting, importing and binding image.",				testImageExportImportBindBind,	imageConfig);
4977 
4978 			dedicatedGroup->addChild(imageGroup.release());
4979 		}
4980 
4981 		group->addChild(dedicatedGroup.release());
4982 	}
4983 
4984 	if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4985 	{
4986 		de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4987 
4988 		const vk::VkFormat	ahbFormats[]	=
4989 		{
4990 			vk::VK_FORMAT_R8G8B8_UNORM,
4991 			vk::VK_FORMAT_R8G8B8A8_UNORM,
4992 			vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4993 			vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4994 			vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4995 			vk::VK_FORMAT_D16_UNORM,
4996 			vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4997 			vk::VK_FORMAT_D24_UNORM_S8_UINT,
4998 			vk::VK_FORMAT_D32_SFLOAT,
4999 			vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
5000 			vk::VK_FORMAT_S8_UINT,
5001 			vk::VK_FORMAT_R8_UNORM,
5002 		};
5003 		const size_t		numOfAhbFormats	= DE_LENGTH_OF_ARRAY(ahbFormats);
5004 
5005 		for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
5006 		{
5007 			const vk::VkFormat	format			= ahbFormats[ahbFormatNdx];
5008 			const std::string	testCaseName	= getFormatCaseName(format);
5009 
5010 			addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
5011 		}
5012 
5013 		group->addChild(formatGroup.release());
5014 	}
5015 
5016 	return group;
5017 }
5018 
createMemoryTests(tcu::TestContext & testCtx)5019 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
5020 {
5021 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
5022 
5023 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5024 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5025 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5026 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
5027 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
5028 	group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA).release());
5029 
5030 	return group;
5031 }
5032 
5033 } // anonymous
5034 
createExternalMemoryTests(tcu::TestContext & testCtx)5035 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
5036 {
5037 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
5038 
5039 	group->addChild(createSemaphoreTests(testCtx).release());
5040 	group->addChild(createMemoryTests(testCtx).release());
5041 	group->addChild(createFenceTests(testCtx).release());
5042 
5043 	return group.release();
5044 }
5045 
5046 } // api
5047 } // vkt
5048