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