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
66using tcu::TestLog;
67using namespace vkt::ExternalMemoryUtil;
68
69namespace vkt
70{
71namespace api
72{
73namespace
74{
75
76
77template<typename T, int size>
78T 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
86std::string getFormatCaseName (vk::VkFormat format)
87{
88	return de::toLower(de::toString(getFormatStr(format)).substr(10));
89}
90
91vk::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
120vk::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
149void 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
164void 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
180std::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
193deUint32 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
208std::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
233CustomInstance 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
251vk::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
429vk::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
440uint32_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
449void 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
477void 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
505void 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
541void 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
598void 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
621void 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
726void 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
815void 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
839void 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
862void 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
951struct TestSemaphoreQueriesParameters
952{
953	vk::VkSemaphoreType							semaphoreType;
954	vk::VkExternalSemaphoreHandleTypeFlagBits	externalType;
955
956	TestSemaphoreQueriesParameters (vk::VkSemaphoreType							semaphoreType_,
957									vk::VkExternalSemaphoreHandleTypeFlagBits	externalType_)
958		: semaphoreType	(semaphoreType_)
959		, externalType	(externalType_)
960	{}
961};
962
963tcu::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
1013struct SemaphoreTestConfig
1014{
1015													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
1026template<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
1046tcu::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
1118tcu::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
1170tcu::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
1222tcu::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
1260tcu::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
1297tcu::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
1331tcu::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
1384tcu::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
1423tcu::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
1449tcu::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
1495tcu::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
1551tcu::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
1646tcu::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
1714tcu::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
1787tcu::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
1860tcu::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
2005tcu::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
2037struct FenceTestConfig
2038{
2039												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
2050tcu::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
2122tcu::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
2174tcu::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
2226tcu::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
2264tcu::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
2289tcu::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
2326tcu::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
2360tcu::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
2413tcu::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
2482tcu::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
2521tcu::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
2567tcu::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
2623tcu::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
2724tcu::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
2792tcu::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
2865tcu::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
2938tcu::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
3083tcu::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
3208tcu::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
3255struct MemoryTestConfig
3256{
3257												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)
3272deUint32 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
3281tcu::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
3363deUint32 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
3374tcu::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
3459tcu::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
3522tcu::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
3552tcu::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
3593tcu::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
3657tcu::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
3722tcu::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
3787tcu::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
3932struct BufferTestConfig
3933{
3934											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
3945tcu::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
4010tcu::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
4074tcu::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
4138tcu::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
4297struct ImageTestConfig
4298{
4299											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
4310tcu::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
4356tcu::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
4410tcu::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
4462template<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
4468template<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
4475de::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
4560void 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
4576bool 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
4656bool 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
4731tcu::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
5030tcu::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
5372void checkMaintenance5(Context& context, vk::VkExternalMemoryHandleTypeFlagBits)
5373{
5374	context.requireDeviceFunctionality("VK_KHR_maintenance5");
5375}
5376
5377de::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
5389de::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
5485de::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
5499de::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
5630de::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
5646tcu::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