1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group 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 *//*!
20 * \file
21 * \brief Modifiers tests
22 *//*--------------------------------------------------------------------*/
23
24#include "vktModifiersTests.hpp"
25#include "vktTestCase.hpp"
26#include "vktTestGroupUtil.hpp"
27#include "vktTestCaseUtil.hpp"
28#include "vktExternalMemoryUtil.hpp"
29#include "vktImageTestsUtil.hpp"
30#include "vkRefUtil.hpp"
31#include "vkBufferWithMemory.hpp"
32#include "vkBarrierUtil.hpp"
33#include "vkCmdUtil.hpp"
34#include "vkObjUtil.hpp"
35#include "vkImageUtil.hpp"
36#include "vkTypeUtil.hpp"
37#include "tcuTestLog.hpp"
38#include "tcuTexture.hpp"
39#include "tcuTextureUtil.hpp"
40#include "tcuImageIO.hpp"
41#include "tcuImageCompare.hpp"
42#include "tcuMaybe.hpp"
43#include "deUniquePtr.hpp"
44#include "deStringUtil.hpp"
45
46#include <string>
47#include <vector>
48#include <algorithm>
49#include <iterator>
50
51namespace vkt
52{
53namespace modifiers
54{
55namespace
56{
57using namespace vk;
58using tcu::UVec2;
59using tcu::TestLog;
60
61struct ExplicitModifier
62{
63	uint64_t				modifier;
64	uint32_t				modifierPlaneCount;
65	VkSubresourceLayout*	pPlaneLayouts;
66};
67
68void checkModifiersSupported (Context& context, VkFormat format)
69{
70	if (!context.isDeviceFunctionalitySupported("VK_EXT_image_drm_format_modifier"))
71		TCU_THROW(NotSupportedError, "VK_EXT_image_drm_format_modifier is not supported");
72
73	if (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))
74		TCU_THROW(NotSupportedError, "VK_KHR_get_physical_device_properties2 not supported");
75
76	if (!context.isDeviceFunctionalitySupported("VK_KHR_bind_memory2"))
77		TCU_THROW(NotSupportedError, "VK_KHR_bind_memory2 not supported");
78
79	if (!context.isDeviceFunctionalitySupported("VK_KHR_image_format_list"))
80		TCU_THROW(NotSupportedError, "VK_KHR_image_format_list not supported");
81
82#ifndef CTS_USES_VULKANSC
83	if (format == VK_FORMAT_A8_UNORM_KHR || format == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
84		context.requireDeviceFunctionality("VK_KHR_maintenance5");
85#endif // CTS_USES_VULKANSC
86}
87
88void checkModifiersList2Supported (Context& context, VkFormat fmt)
89{
90	checkModifiersSupported(context, fmt);
91
92	if (!context.isDeviceFunctionalitySupported("VK_KHR_format_feature_flags2"))
93		TCU_THROW(NotSupportedError, "VK_KHR_format_feature_flags2 not supported");
94}
95
96std::string getFormatCaseName (VkFormat format)
97{
98	return de::toLower(de::toString(getFormatStr(format)).substr(10));
99}
100
101template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
102std::vector<ModifierProps> getDrmFormatModifiers (const InstanceInterface&	vki,
103												  VkPhysicalDevice			physicalDevice,
104												  VkFormat					format)
105{
106	ModifierList									modifierProperties;
107	deMemset(&modifierProperties, 0, sizeof(modifierProperties));
108
109	modifierProperties.sType = modifierListSType;
110	VkFormatProperties2								formatProperties;
111	deMemset(&formatProperties, 0, sizeof(formatProperties));
112
113	std::vector<ModifierProps>						drmFormatModifiers;
114	formatProperties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
115	formatProperties.pNext = &modifierProperties;
116
117	vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties);
118
119	drmFormatModifiers.resize(modifierProperties.drmFormatModifierCount);
120	modifierProperties.pDrmFormatModifierProperties = drmFormatModifiers.data();
121
122	vki.getPhysicalDeviceFormatProperties2(physicalDevice, format, &formatProperties);
123
124	return drmFormatModifiers;
125}
126
127// Returns true if the image with the given parameters and modifiers supports the given handle type.
128bool verifyHandleTypeForFormatModifier (const InstanceInterface&				vki,
129									    VkPhysicalDevice						physicalDevice,
130									    const VkFormat							format,
131									    const VkImageType						imageType,
132									    const VkImageUsageFlags					imageUsages,
133									    const VkExternalMemoryHandleTypeFlags	handleType,
134									    const deUint64							drmFormatModifier)
135{
136	const VkPhysicalDeviceImageDrmFormatModifierInfoEXT imageFormatModifierInfo =
137	{
138		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
139		DE_NULL,
140		drmFormatModifier,
141		VK_SHARING_MODE_EXCLUSIVE,
142		0,
143		DE_NULL,
144	};
145
146	const VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo =
147	{
148		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
149		&imageFormatModifierInfo,
150		(VkExternalMemoryHandleTypeFlagBits)handleType,
151	};
152
153	const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
154	{
155		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
156		&externalImageFormatInfo,
157		format,
158		imageType,
159		VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
160		imageUsages,
161		0,
162	};
163
164	VkExternalImageFormatProperties	externalImageProperties	= initVulkanStructure();
165	VkImageFormatProperties2		imageProperties			= initVulkanStructure(&externalImageProperties);
166
167	if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
168		return false;
169
170	if ((externalImageProperties.externalMemoryProperties.compatibleHandleTypes & handleType) != handleType)
171		return false;
172
173	return true;
174}
175
176template <typename FlagsType>
177static deBool featuresCompatible(FlagsType modifierFeatures, VkFormatFeatureFlags testFeatures)
178{
179	// All the format feature flags alias with their equivalents in the lower
180	// 32 bits of VkFormatFeatureFlags2KHR, so as long as we're casting "up",
181	// this should always be safe
182	DE_STATIC_ASSERT(sizeof(modifierFeatures) >= sizeof(testFeatures));
183	return ((modifierFeatures & static_cast<FlagsType>(testFeatures)) == static_cast<FlagsType>(testFeatures));
184}
185
186template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
187std::vector<ModifierProps> getExportImportCompatibleModifiers (Context& context, VkFormat format)
188{
189	const auto&				vki					= context.getInstanceInterface();
190	const auto				drmFormatModifiers	= getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
191	std::vector<ModifierProps>	compatibleModifiers;
192
193	if (drmFormatModifiers.empty())
194		return compatibleModifiers;
195
196	const VkFormatFeatureFlags testFeatures = (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
197									VK_FORMAT_FEATURE_BLIT_SRC_BIT |
198									VK_FORMAT_FEATURE_BLIT_DST_BIT |
199									VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
200
201	for (const auto& modifierProps : drmFormatModifiers)
202	{
203		if (modifierProps.drmFormatModifierTilingFeatures == 0)
204			TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
205
206		if (!featuresCompatible(modifierProps.drmFormatModifierTilingFeatures, testFeatures))
207			continue;
208
209		const auto&	modifier	= modifierProps.drmFormatModifier;
210		const auto	supported	= verifyHandleTypeForFormatModifier(vki, context.getPhysicalDevice(), format,
211																	VK_IMAGE_TYPE_2D,
212																	(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
213																	VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
214																	modifier);
215
216		if (!supported)
217			continue;
218
219		compatibleModifiers.push_back(modifierProps);
220	}
221
222	return compatibleModifiers;
223}
224
225template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
226void checkExportImportExtensions (Context& context, VkFormat format)
227{
228	// tcuTexture.cpp getChannelSize, that is used by intThresholdCompare does not support the following formats.
229	// TODO: Add tcuTexture.cpp support for the following formats.
230	const VkFormat					skippedFormats[]				=
231	{
232		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
233		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
234		VK_FORMAT_A2R10G10B10_SNORM_PACK32,
235		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
236		VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
237		VK_FORMAT_A2R10G10B10_UINT_PACK32,
238		VK_FORMAT_A2R10G10B10_SINT_PACK32,
239		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
240		VK_FORMAT_A2B10G10R10_SNORM_PACK32,
241		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
242		VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
243		VK_FORMAT_A2B10G10R10_UINT_PACK32,
244		VK_FORMAT_A2B10G10R10_SINT_PACK32,
245		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
246	};
247
248	if (std::find(std::begin(skippedFormats), std::end(skippedFormats), format) != std::end(skippedFormats))
249		TCU_THROW(NotSupportedError, de::toString(format) + " can't be checked for correctness");
250
251	if (!context.isDeviceFunctionalitySupported("VK_KHR_external_memory_fd"))
252		TCU_THROW(NotSupportedError, "VK_KHR_external_memory_fd not supported");
253
254	if (modifierListSType == VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT)
255		checkModifiersSupported(context, format);
256	else
257		checkModifiersList2Supported(context, format);
258
259	const auto compatibleModifiers = getExportImportCompatibleModifiers<ModifierList, ModifierProps, modifierListSType>(context, format);
260	if (compatibleModifiers.empty())
261		TCU_THROW(NotSupportedError, "Could not find a format modifier supporting required transfer features for " + de::toString(format));
262}
263
264deBool isModifierCompatibleWithImageProperties (const InstanceInterface&				vki,
265												VkPhysicalDevice						physicalDevice,
266												const VkFormat*							formats,
267												const deUint32							nFormats,
268												const VkImageType						imageType,
269												const VkImageUsageFlags					imageUsages,
270												const VkExternalMemoryHandleTypeFlags	handleType,
271												const deUint64							drmFormatModifier,
272												VkImageFormatProperties2&				imageProperties)
273{
274	const VkPhysicalDeviceImageDrmFormatModifierInfoEXT	imageFormatModifierInfo	=
275	{
276		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
277		DE_NULL,
278		drmFormatModifier,
279		VK_SHARING_MODE_EXCLUSIVE,
280		0,
281		DE_NULL,
282	};
283
284	const VkPhysicalDeviceExternalImageFormatInfo	externalImageFormatInfo =
285	{
286		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
287		&imageFormatModifierInfo,
288		(VkExternalMemoryHandleTypeFlagBits)handleType,
289	};
290
291	const VkImageFormatListCreateInfo				imageFormatListInfo		=
292	{
293		VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
294		&externalImageFormatInfo,
295		nFormats,
296		formats,
297	};
298
299	const VkPhysicalDeviceImageFormatInfo2			imageFormatInfo			=
300	{
301		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
302		&imageFormatListInfo,
303		formats[0],
304		imageType,
305		VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
306		imageUsages,
307		0,
308	};
309
310	VkExternalImageFormatProperties	externalImageProperties	= initVulkanStructure();
311	imageProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
312	imageProperties.pNext = &externalImageProperties;
313
314	if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
315		return false;
316
317	if ((externalImageProperties.externalMemoryProperties.compatibleHandleTypes & handleType) != handleType)
318		return false;
319
320	return true;
321}
322
323template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
324tcu::TestStatus listModifiersCase (Context& context, VkFormat format)
325{
326	TestLog&					log					= context.getTestContext().getLog();
327	const InstanceInterface&	vki					= context.getInstanceInterface();
328	const auto					drmFormatModifiers	= getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
329	bool											noneCompatible		= true;
330
331	if (drmFormatModifiers.empty())
332		TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers");
333
334	for (deUint32 m = 0; m < drmFormatModifiers.size(); m++) {
335		VkImageFormatProperties2	imageProperties {};
336		deBool						isCompatible	= isModifierCompatibleWithImageProperties(vki, context.getPhysicalDevice(),
337																							  &format, 1u, VK_IMAGE_TYPE_2D,
338																							  (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
339																							  VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
340																							  drmFormatModifiers[m].drmFormatModifier, imageProperties);
341
342		if (drmFormatModifiers[m].drmFormatModifierTilingFeatures == 0)
343			TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
344
345		if (!isCompatible)
346			continue;
347		noneCompatible = false;
348
349		TCU_CHECK(imageProperties.imageFormatProperties.maxExtent.width >= 1 && imageProperties.imageFormatProperties.maxExtent.height >= 1);
350		TCU_CHECK(imageProperties.imageFormatProperties.maxArrayLayers >= 1);
351
352		log << TestLog::Message
353			<< "format modifier " << m << ":\n"
354			<< drmFormatModifiers[m] << "\n"
355			<< imageProperties
356			<< TestLog::EndMessage;
357	}
358
359	if (noneCompatible)
360		TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers for the requested image features");
361
362	return tcu::TestStatus::pass("OK");
363}
364
365Move<VkImage> createImageNoModifiers (const DeviceInterface&			vkd,
366												 const VkDevice					device,
367												 const VkImageUsageFlags		imageUsages,
368												 const VkFormat					format,
369												 const UVec2&					size)
370{
371	const VkImageCreateInfo							createInfo	=
372	{
373		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
374		DE_NULL,
375		0,
376		VK_IMAGE_TYPE_2D,
377		format,
378		makeExtent3D(size.x(), size.y(), 1u),
379		1u,		// mipLevels
380		1u,		// arrayLayers
381		VK_SAMPLE_COUNT_1_BIT,
382		VK_IMAGE_TILING_OPTIMAL,
383		imageUsages,
384		VK_SHARING_MODE_EXCLUSIVE,
385		0u,
386		(const deUint32*)DE_NULL,
387		VK_IMAGE_LAYOUT_PREINITIALIZED,
388	};
389
390	return createImage(vkd, device, &createInfo);
391}
392
393Move<VkImage> createImageWithDrmFormatExplicitModifier (const DeviceInterface&					vkd,
394														const VkDevice							device,
395														const VkImageType						imageType,
396														const VkImageUsageFlags					imageUsages,
397														const VkExternalMemoryHandleTypeFlags	externalMemoryHandleTypeFlags,
398														const std::vector<VkFormat>&			formats,
399														const UVec2&							size,
400														const ExplicitModifier					drmFormatModifier)
401{
402	const VkImageDrmFormatModifierExplicitCreateInfoEXT	modifierExplicitCreateInfo =
403	{
404		VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
405		DE_NULL,
406		drmFormatModifier.modifier,
407		drmFormatModifier.modifierPlaneCount,
408		drmFormatModifier.pPlaneLayouts,
409	};
410
411	const VkExternalMemoryImageCreateInfo externalMemoryCreateInfo =
412	{
413		VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
414		&modifierExplicitCreateInfo,
415		externalMemoryHandleTypeFlags,
416	};
417
418	const void* pNext = &externalMemoryCreateInfo;
419	if (!externalMemoryHandleTypeFlags)
420	{
421		pNext = &modifierExplicitCreateInfo;
422	}
423
424	const VkImageFormatListCreateInfo			imageFormatListInfo			=
425	{
426		VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
427		pNext,
428		de::sizeU32(formats),
429		de::dataOrNull(formats),
430	};
431
432	const VkImageCreateInfo							createInfo	=
433	{
434		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
435		&imageFormatListInfo,
436		0,
437		imageType,
438		formats.front(),
439		makeExtent3D(size.x(), size.y(), 1u),
440		1u,		// mipLevels
441		1u,		// arrayLayers
442		VK_SAMPLE_COUNT_1_BIT,
443		VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
444		imageUsages,
445		VK_SHARING_MODE_EXCLUSIVE,
446		0u,
447		nullptr,
448		VK_IMAGE_LAYOUT_UNDEFINED,
449	};
450
451	return createImage(vkd, device, &createInfo);
452}
453
454Move<VkImage> createImageWithDrmFormatModifiers (const DeviceInterface&					vkd,
455												 const VkDevice							device,
456												 const VkImageType						imageType,
457												 const VkImageUsageFlags				imageUsages,
458												 const VkExternalMemoryHandleTypeFlags	externalMemoryHandleTypeFlags,
459												 const std::vector<VkFormat>&			formats,
460												 const UVec2&							size,
461												 const std::vector<deUint64>&			drmFormatModifiers)
462{
463	const VkImageDrmFormatModifierListCreateInfoEXT	modifierListCreateInfo =
464	{
465		VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
466		DE_NULL,
467		(deUint32)drmFormatModifiers.size(),
468		drmFormatModifiers.data(),
469	};
470
471	const VkExternalMemoryImageCreateInfo externalMemoryCreateInfo =
472	{
473		VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
474		&modifierListCreateInfo,
475		externalMemoryHandleTypeFlags,
476	};
477
478	const void* pNext = &externalMemoryCreateInfo;
479	if (!externalMemoryHandleTypeFlags)
480	{
481		pNext = &modifierListCreateInfo;
482	}
483
484	const VkImageFormatListCreateInfo			imageFormatListInfo			=
485	{
486		VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
487		pNext,
488		static_cast<deUint32>(formats.size()),
489		formats.data(),
490	};
491
492	const VkImageCreateInfo							createInfo	=
493	{
494		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
495		&imageFormatListInfo,
496		0,
497		imageType,
498		formats.front(),
499		makeExtent3D(size.x(), size.y(), 1u),
500		1u,		// mipLevels
501		1u,		// arrayLayers
502		VK_SAMPLE_COUNT_1_BIT,
503		VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
504		imageUsages,
505		VK_SHARING_MODE_EXCLUSIVE,
506		0u,
507		(const deUint32*)DE_NULL,
508		VK_IMAGE_LAYOUT_UNDEFINED,
509	};
510
511	return createImage(vkd, device, &createInfo);
512}
513
514template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
515tcu::TestStatus createImageListModifiersCase (Context& context, const VkFormat format)
516{
517	const InstanceInterface&	vki					= context.getInstanceInterface();
518	const DeviceInterface&		vkd					= context.getDeviceInterface();
519	const VkDevice				device				= context.getDevice();
520	const auto					drmFormatModifiers	= getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
521
522	if (drmFormatModifiers.empty())
523		TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers");
524
525	// Get the list of modifiers supported for some specific image parameters.
526	std::vector<deUint64> modifiers;
527
528	for (const auto& modProps : drmFormatModifiers)
529	{
530		VkImageFormatProperties2	imgFormatProperties	= initVulkanStructure();
531		const auto					isCompatible		= isModifierCompatibleWithImageProperties(vki, context.getPhysicalDevice(), &format, 1u, VK_IMAGE_TYPE_2D,
532																								  (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
533																								  VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
534																								  modProps.drmFormatModifier, imgFormatProperties);
535		if (isCompatible)
536			modifiers.push_back(modProps.drmFormatModifier);
537		if (modProps.drmFormatModifierTilingFeatures == 0)
538			TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
539	}
540
541	if (modifiers.empty())
542		TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers for the requested image features");
543
544	// Test with lists of compatible modifiers of increasing lengths.
545	for (size_t len = 1u; len <= modifiers.size(); ++len)
546	{
547		std::vector<deUint64> creationModifiers;
548		creationModifiers.reserve(len);
549		std::copy_n(begin(modifiers), len, std::back_inserter(creationModifiers));
550
551		VkImageDrmFormatModifierPropertiesEXT	properties	= initVulkanStructure();
552
553		{
554			std::vector<VkFormat>	formats	(1u, format);
555			const auto				image	= createImageWithDrmFormatModifiers(vkd, device, VK_IMAGE_TYPE_2D,
556																				(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
557																				0, formats, UVec2(64, 64), creationModifiers);
558
559			VK_CHECK(vkd.getImageDrmFormatModifierPropertiesEXT(device, *image, &properties));
560		}
561
562		if (!de::contains(begin(creationModifiers), end(creationModifiers), properties.drmFormatModifier))
563			return tcu::TestStatus::fail("Image created with modifier not specified in the create list");
564	}
565
566	return tcu::TestStatus::pass("OK");
567}
568
569template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
570tcu::TestStatus createImageModifierExplicitCase (Context& context, const VkFormat format)
571{
572	const InstanceInterface&	vki					= context.getInstanceInterface();
573	const DeviceInterface&		vkd					= context.getDeviceInterface();
574	const VkDevice				device				= context.getDevice();
575	const auto					drmFormatModifiers	= getDrmFormatModifiers<ModifierList, ModifierProps, modifierListSType>(vki, context.getPhysicalDevice(), format);
576
577	if (drmFormatModifiers.empty())
578		TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers");
579
580	// Get the list of modifiers supported for some specific image parameters.
581	std::vector<ExplicitModifier> modifiers;
582
583	for (const auto& modProps : drmFormatModifiers)
584	{
585		if (modProps.drmFormatModifierTilingFeatures == 0)
586			TCU_FAIL(de::toString(format) + " does not support any DRM modifier tiling features");
587
588		VkImageFormatProperties2	imgFormatProperties	= initVulkanStructure();
589		const auto					isCompatible		= isModifierCompatibleWithImageProperties(vki, context.getPhysicalDevice(), &format, 1u, VK_IMAGE_TYPE_2D,
590																								  (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
591																								  VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
592																								  modProps.drmFormatModifier, imgFormatProperties);
593		if (isCompatible)
594		{
595			const ExplicitModifier modifier =
596			{
597				modProps.drmFormatModifier,				// modifier
598				modProps.drmFormatModifierPlaneCount,	// modifierPlaneCount
599				DE_NULL,								// pPlaneLayouts
600			};
601
602			modifiers.push_back(modifier);
603		}
604	}
605
606	if (modifiers.empty())
607		TCU_THROW(NotSupportedError, de::toString(format) + " does not support any DRM modifiers for the requested image features");
608
609	for (auto& modifier : modifiers)
610	{
611		std::vector<VkFormat> formats			(1u, format);
612		std::vector<uint64_t> creationModifier	(1u, modifier.modifier);
613
614		VkImageDrmFormatModifierPropertiesEXT properties = initVulkanStructure();
615
616		const auto imageRef = createImageWithDrmFormatModifiers(vkd, device, VK_IMAGE_TYPE_2D,
617																(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
618																0, formats, UVec2(64, 64), creationModifier);
619
620		std::vector<VkSubresourceLayout>	planeLayouts;
621		for (uint32_t i = 0; i < modifier.modifierPlaneCount; i++)
622		{
623			VkImageSubresource imageSubresource;
624			VkSubresourceLayout subresourceLayout;
625
626			deMemset(&imageSubresource, 0, sizeof(imageSubresource));
627
628			imageSubresource.aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT << i;
629
630			vkd.getImageSubresourceLayout(device, *imageRef, &imageSubresource, &subresourceLayout);
631
632			// From the spec:
633			//   VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-size-02267
634			//   For each element of pPlaneLayouts, size must be 0
635			//
636			//   VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-arrayPitch-02268
637			//   For each element of pPlaneLayouts, arrayPitch must be 0 if VkImageCreateInfo::arrayLayers is 1
638			//
639			//   VUID-VkImageDrmFormatModifierExplicitCreateInfoEXT-depthPitch-02269
640			//   For each element of pPlaneLayouts, depthPitch must be 0 if VkImageCreateInfo::extent.depth is 1
641			subresourceLayout.size = 0;
642			subresourceLayout.arrayPitch = 0;
643			subresourceLayout.depthPitch = 0;
644
645			planeLayouts.push_back(subresourceLayout);
646
647		}
648		modifier.pPlaneLayouts = planeLayouts.data();
649
650		const auto image = createImageWithDrmFormatExplicitModifier(vkd, device, VK_IMAGE_TYPE_2D,
651																    (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
652																    0, formats, UVec2(64, 64), modifier);
653		VK_CHECK(vkd.getImageDrmFormatModifierPropertiesEXT(device, *image, &properties));
654
655		if (modifier.modifier != properties.drmFormatModifier)
656			return tcu::TestStatus::fail("The created image's modifier with an explicit modifier not matched");
657	}
658
659	return tcu::TestStatus::pass("OK");
660}
661
662deUint32 chooseMemoryType(deUint32 bits)
663{
664	DE_ASSERT(bits != 0);
665
666	for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= bits; memoryTypeIndex++)
667	{
668		if ((bits & (1u << memoryTypeIndex)) != 0)
669			return memoryTypeIndex;
670	}
671
672	DE_FATAL("No supported memory types");
673	return -1;
674}
675
676template <typename ModifierProps>
677bool exportImportMemoryExplicitModifiersCase (Context& context, const VkFormat format, const ModifierProps& modifier)
678{
679	const InstanceInterface&						vki					= context.getInstanceInterface();
680	const DeviceInterface&							vkd					= context.getDeviceInterface();
681	const VkDevice									device				= context.getDevice();
682
683
684	const auto supported = verifyHandleTypeForFormatModifier(vki, context.getPhysicalDevice(), format,
685															 VK_IMAGE_TYPE_2D,
686															 (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT),
687															 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
688															 modifier.drmFormatModifier);
689
690	if (!supported)
691		TCU_FAIL("Modifier " + de::toString(modifier.drmFormatModifier) + " for format " + de::toString(format) + " expected to be compatible");
692
693	std::vector<deUint64>					modifiers;
694	modifiers.push_back(modifier.drmFormatModifier);
695
696
697	const UVec2									imageSize		(64, 64);
698	const tcu::TextureFormat referenceTextureFormat (mapVkFormat(format));
699	deUint32 bufferSize = 1<<16;
700	const de::UniquePtr<BufferWithMemory>		inputBuffer		(new BufferWithMemory(vkd, device, context.getDefaultAllocator(),
701																																							makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT),
702																						MemoryRequirement::HostVisible));
703	tcu::PixelBufferAccess				referenceImage	(referenceTextureFormat, imageSize.x(), imageSize.y(), 1, inputBuffer->getAllocation().getHostPtr());
704	const de::UniquePtr<BufferWithMemory>		outputBuffer		(new BufferWithMemory(vkd, device, context.getDefaultAllocator(),
705																																							makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
706																						MemoryRequirement::HostVisible));
707	Unique<VkCommandPool>			cmdPool				(createCommandPool(vkd, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex(), DE_NULL));
708	vkt::ExternalMemoryUtil::NativeHandle								inputImageMemFd;
709
710	const tcu::TextureFormatInfo				formatInfo		(tcu::getTextureFormatInfo(referenceTextureFormat));
711	tcu::fillWithComponentGradients(referenceImage, formatInfo.valueMin, formatInfo.valueMax);
712
713	flushAlloc(vkd, device, inputBuffer->getAllocation());
714
715	Move<VkImage>						srcImage		(createImageNoModifiers(vkd, device,
716																								 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
717																								 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
718																								 format, UVec2(64, 64)));
719	VkMemoryRequirements srcImageMemoryReq = getImageMemoryRequirements(vkd, device, *srcImage);
720	const vk::VkMemoryAllocateInfo	allocationInfo	=
721	{
722		vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
723		DE_NULL,
724		srcImageMemoryReq.size,
725		chooseMemoryType(srcImageMemoryReq.memoryTypeBits),
726	};
727	vk::Move<vk::VkDeviceMemory>	srcMemory			(vk::allocateMemory(vkd, device, &allocationInfo));
728	VK_CHECK(vkd.bindImageMemory(device, *srcImage, *srcMemory, 0));
729
730
731	Unique<VkCommandBuffer>			cmdBuffer			(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
732	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
733	{
734		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
735		DE_NULL,
736		VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
737		(const VkCommandBufferInheritanceInfo*)DE_NULL,
738	};
739
740	VK_CHECK(vkd.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
741
742	{
743		const VkImageAspectFlags		aspect				= VK_IMAGE_ASPECT_COLOR_BIT;
744		std::vector<VkBufferImageCopy>	copies;
745
746		copies.push_back(image::makeBufferImageCopy(makeExtent3D(imageSize.x(), imageSize.y(), 1u), 1u));
747		copyBufferToImage(vkd, *cmdBuffer, inputBuffer->get(), bufferSize,
748											copies, aspect, 1, 1, *srcImage,
749											VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
750
751	}
752
753	Move<VkImage>						dstImage		(createImageWithDrmFormatModifiers(vkd, device, VK_IMAGE_TYPE_2D,
754																																				 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
755																																				 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
756																																				 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
757																																				 {format}, UVec2(64, 64), modifiers));
758	VkMemoryRequirements dstImageMemoryReq = getImageMemoryRequirements(vkd, device, *dstImage);
759	vk::Move<vk::VkDeviceMemory>	dstMemory			(vkt::ExternalMemoryUtil::allocateExportableMemory(vkd, device,
760																																																 dstImageMemoryReq.size,
761																																																 chooseMemoryType(dstImageMemoryReq.memoryTypeBits),
762																																																 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
763																																																 *dstImage));
764
765	VK_CHECK(vkd.bindImageMemory(device, *dstImage, *dstMemory, 0));
766	const VkImageMemoryBarrier		srcImageBarrier		=
767	{
768		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
769		DE_NULL,									// const void*				pNext;
770		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
771		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
772		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
773		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout			newLayout;
774		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
775		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
776		*srcImage,						// VkImage					image;
777		{											// VkImageSubresourceRange	subresourceRange;
778			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
779			0u,								// deUint32				baseMipLevel;
780			1u,								// deUint32				mipLevels;
781			0u,								// deUint32				baseArraySlice;
782			1u								// deUint32				arraySize;
783		}
784	};
785	const VkImageMemoryBarrier		dstImageBarrier		=
786	{
787		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
788		DE_NULL,									// const void*				pNext;
789		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
790		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
791		VK_IMAGE_LAYOUT_UNDEFINED,		// VkImageLayout			oldLayout;
792		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
793		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
794		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
795		*dstImage,						// VkImage					image;
796		{											// VkImageSubresourceRange	subresourceRange;
797			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
798			0u,								// deUint32				baseMipLevel;
799			1u,								// deUint32				mipLevels;
800			0u,								// deUint32				baseArraySlice;
801			1u								// deUint32				arraySize;
802		}
803	};
804	vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &srcImageBarrier);
805	vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &dstImageBarrier);
806
807	VkImageBlit		imageBlit
808	{
809		{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
810		{{0,0,0}, {64,64,1}},
811		{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
812		{{0,0,0}, {64,64,1}},
813	};
814	vkd.cmdBlitImage(*cmdBuffer, *srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit, VK_FILTER_NEAREST);
815
816	const VkImageMemoryBarrier		exportImageBarrier		=
817	{
818		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
819		DE_NULL,									// const void*				pNext;
820		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
821		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
822		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
823		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
824		context.getUniversalQueueFamilyIndex(),		// deUint32					dstQueueFamilyIndex;
825		VK_QUEUE_FAMILY_FOREIGN_EXT,				// deUint32					srcQueueFamilyIndex;
826		*dstImage,									// VkImage					image;
827		{											// VkImageSubresourceRange	subresourceRange;
828			VK_IMAGE_ASPECT_COLOR_BIT,		// VkImageAspectFlags		aspectMask;
829			0u,								// deUint32					baseMipLevel;
830			1u,								// deUint32					mipLevels;
831			0u,								// deUint32					baseArraySlice;
832			1u								// deUint32					arraySize;
833		}
834	};
835
836	vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &exportImageBarrier);
837	VK_CHECK(vkd.endCommandBuffer(*cmdBuffer));
838	submitCommandsAndWait(vkd, device, context.getUniversalQueue(), *cmdBuffer);
839	VkImageDrmFormatModifierPropertiesEXT	properties;
840	deMemset(&properties, 0, sizeof(properties));
841	properties.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT;
842	VK_CHECK(vkd.getImageDrmFormatModifierPropertiesEXT(device, *dstImage, &properties));
843	TCU_CHECK(properties.drmFormatModifier == modifiers.front());
844	inputImageMemFd	= vkt::ExternalMemoryUtil::getMemoryFd(vkd, device, *dstMemory, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
845
846	ExplicitModifier explicitModifier =
847	{
848		modifier.drmFormatModifier,
849		modifier.drmFormatModifierPlaneCount,
850		DE_NULL,								// pPlaneLayouts
851	};
852	std::vector<VkSubresourceLayout>	planeLayouts;
853	for (uint32_t i = 0; i < modifier.drmFormatModifierPlaneCount; i++)
854	{
855		VkImageSubresource imageSubresource;
856		VkSubresourceLayout subresourceLayout;
857
858		deMemset(&imageSubresource, 0, sizeof(imageSubresource));
859
860		imageSubresource.aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT << i;
861
862		vkd.getImageSubresourceLayout(device, *dstImage, &imageSubresource, &subresourceLayout);
863
864		subresourceLayout.size = 0;
865		subresourceLayout.arrayPitch = 0;
866		subresourceLayout.depthPitch = 0;
867
868		planeLayouts.push_back(subresourceLayout);
869
870	}
871	explicitModifier.pPlaneLayouts = planeLayouts.data();
872
873	Move<VkImage>				importedSrcImage		(createImageWithDrmFormatExplicitModifier(vkd, device, VK_IMAGE_TYPE_2D,
874																																						 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
875																																						 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
876																																						 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
877																																						 {format}, UVec2(64, 64), explicitModifier));
878
879	VkMemoryRequirements importedSrcImageMemoryReq = getImageMemoryRequirements(vkd, device, *importedSrcImage);
880
881	Move<VkDeviceMemory>						importedMemory (vkt::ExternalMemoryUtil::importDedicatedMemory(vkd, device, *importedSrcImage,
882                                                                                                               importedSrcImageMemoryReq,
883                                                                                                               VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
884                                                                                                               ~0u, inputImageMemFd));
885	VK_CHECK(vkd.bindImageMemory(device, *importedSrcImage, *importedMemory, 0));
886
887	Move<VkImage>						outImage		(createImageNoModifiers(vkd, device,
888																															VK_IMAGE_USAGE_TRANSFER_DST_BIT |
889																															VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
890																															format, UVec2(64, 64)));
891	VkMemoryRequirements outImageMemoryReq = getImageMemoryRequirements(vkd, device, *outImage);
892	const vk::VkMemoryAllocateInfo	outAllocationInfo	=
893	{
894		vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
895		DE_NULL,
896		outImageMemoryReq.size,
897		chooseMemoryType(outImageMemoryReq.memoryTypeBits),
898	};
899	vk::Move<vk::VkDeviceMemory>	outMemory			(vk::allocateMemory(vkd, device, &outAllocationInfo));
900	VK_CHECK(vkd.bindImageMemory(device, *outImage, *outMemory, 0));
901
902	Unique<VkCommandBuffer>			cmdBuffer2			(allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
903	VK_CHECK(vkd.beginCommandBuffer(*cmdBuffer2, &cmdBufferBeginInfo));
904
905	const VkImageMemoryBarrier		importedImageBarrier		=
906	{
907		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
908		DE_NULL,									// const void*				pNext;
909		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
910		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
911		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			oldLayout;
912		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// VkImageLayout			newLayout;
913		VK_QUEUE_FAMILY_FOREIGN_EXT,					// deUint32					srcQueueFamilyIndex;
914		context.getUniversalQueueFamilyIndex(),			// deUint32					dstQueueFamilyIndex;
915		*importedSrcImage,						// VkImage					image;
916		{											// VkImageSubresourceRange	subresourceRange;
917			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
918			0u,								// deUint32				baseMipLevel;
919			1u,								// deUint32				mipLevels;
920			0u,								// deUint32				baseArraySlice;
921			1u								// deUint32				arraySize;
922		}
923	};
924	const VkImageMemoryBarrier		outImageBarrier		=
925	{
926		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
927		DE_NULL,									// const void*				pNext;
928		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
929		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
930		VK_IMAGE_LAYOUT_UNDEFINED,		// VkImageLayout			oldLayout;
931		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,			// VkImageLayout			newLayout;
932		VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
933		VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
934		*outImage,						// VkImage					image;
935		{											// VkImageSubresourceRange	subresourceRange;
936			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
937			0u,								// deUint32				baseMipLevel;
938			1u,								// deUint32				mipLevels;
939			0u,								// deUint32				baseArraySlice;
940			1u								// deUint32				arraySize;
941		}
942	};
943
944	vkd.cmdPipelineBarrier(*cmdBuffer2, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &importedImageBarrier);
945	vkd.cmdPipelineBarrier(*cmdBuffer2, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &outImageBarrier);
946
947	VkImageBlit		imageBlit2
948	{
949		{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
950		{{0,0,0}, {64,64,1}},
951		{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
952		{{0,0,0}, {64,64,1}},
953	};
954	vkd.cmdBlitImage(*cmdBuffer2, *importedSrcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *outImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageBlit2, VK_FILTER_NEAREST);
955
956
957	copyImageToBuffer(vkd, *cmdBuffer2, *outImage,
958										outputBuffer->get(), tcu::IVec2(imageSize.x(), imageSize.y()),
959										VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1);
960
961	VK_CHECK(vkd.endCommandBuffer(*cmdBuffer2));
962
963	submitCommandsAndWait(vkd, device, context.getUniversalQueue(), *cmdBuffer2);
964
965
966	tcu::ConstPixelBufferAccess	result	(referenceTextureFormat, imageSize.x(), imageSize.y(), 1, outputBuffer->getAllocation().getHostPtr());
967	const tcu::UVec4 threshold (0u);
968
969	invalidateAlloc(vkd, device, outputBuffer->getAllocation());
970
971	return tcu::intThresholdCompare(context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage, result, threshold, tcu::COMPARE_LOG_RESULT);
972}
973
974template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
975tcu::TestStatus exportImportMemoryExplicitModifiersCase (Context& context, const VkFormat format)
976{
977	const auto compatibleModifiers = getExportImportCompatibleModifiers<ModifierList, ModifierProps, modifierListSType>(context, format);
978
979	if (compatibleModifiers.empty())
980		TCU_FAIL("Expected non-empty list of compatible modifiers for the given format");
981
982	for (const auto& modifier : compatibleModifiers)
983	{
984		if (!exportImportMemoryExplicitModifiersCase(context, format, modifier))
985			return tcu::TestStatus::fail("Unexpected copy image result");
986	}
987
988	return tcu::TestStatus::pass("OK");
989}
990
991} // anonymous
992
993tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx, const std::string& name)
994{
995	de::MovePtr<tcu::TestCaseGroup>	drmFormatModifiersGroup	(new tcu::TestCaseGroup(testCtx, name.c_str()));
996	const VkFormat					formats[]				=
997	{
998		VK_FORMAT_R4G4_UNORM_PACK8,
999		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
1000		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1001		VK_FORMAT_R5G6B5_UNORM_PACK16,
1002		VK_FORMAT_B5G6R5_UNORM_PACK16,
1003		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
1004		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
1005		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1006#ifndef CTS_USES_VULKANSC
1007		VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
1008#endif // CTS_USES_VULKANSC
1009		VK_FORMAT_R8_UNORM,
1010		VK_FORMAT_R8_SNORM,
1011		VK_FORMAT_R8_USCALED,
1012		VK_FORMAT_R8_SSCALED,
1013		VK_FORMAT_R8_UINT,
1014		VK_FORMAT_R8_SINT,
1015		VK_FORMAT_R8_SRGB,
1016#ifndef CTS_USES_VULKANSC
1017		VK_FORMAT_A8_UNORM_KHR,
1018#endif // CTS_USES_VULKANSC
1019		VK_FORMAT_R8G8_UNORM,
1020		VK_FORMAT_R8G8_SNORM,
1021		VK_FORMAT_R8G8_USCALED,
1022		VK_FORMAT_R8G8_SSCALED,
1023		VK_FORMAT_R8G8_UINT,
1024		VK_FORMAT_R8G8_SINT,
1025		VK_FORMAT_R8G8_SRGB,
1026		VK_FORMAT_R8G8B8_UNORM,
1027		VK_FORMAT_R8G8B8_SNORM,
1028		VK_FORMAT_R8G8B8_USCALED,
1029		VK_FORMAT_R8G8B8_SSCALED,
1030		VK_FORMAT_R8G8B8_UINT,
1031		VK_FORMAT_R8G8B8_SINT,
1032		VK_FORMAT_R8G8B8_SRGB,
1033		VK_FORMAT_B8G8R8_UNORM,
1034		VK_FORMAT_B8G8R8_SNORM,
1035		VK_FORMAT_B8G8R8_USCALED,
1036		VK_FORMAT_B8G8R8_SSCALED,
1037		VK_FORMAT_B8G8R8_UINT,
1038		VK_FORMAT_B8G8R8_SINT,
1039		VK_FORMAT_B8G8R8_SRGB,
1040		VK_FORMAT_R8G8B8A8_UNORM,
1041		VK_FORMAT_R8G8B8A8_SNORM,
1042		VK_FORMAT_R8G8B8A8_USCALED,
1043		VK_FORMAT_R8G8B8A8_SSCALED,
1044		VK_FORMAT_R8G8B8A8_UINT,
1045		VK_FORMAT_R8G8B8A8_SINT,
1046		VK_FORMAT_R8G8B8A8_SRGB,
1047		VK_FORMAT_B8G8R8A8_UNORM,
1048		VK_FORMAT_B8G8R8A8_SNORM,
1049		VK_FORMAT_B8G8R8A8_USCALED,
1050		VK_FORMAT_B8G8R8A8_SSCALED,
1051		VK_FORMAT_B8G8R8A8_UINT,
1052		VK_FORMAT_B8G8R8A8_SINT,
1053		VK_FORMAT_B8G8R8A8_SRGB,
1054		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1055		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1056		VK_FORMAT_A8B8G8R8_USCALED_PACK32,
1057		VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
1058		VK_FORMAT_A8B8G8R8_UINT_PACK32,
1059		VK_FORMAT_A8B8G8R8_SINT_PACK32,
1060		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1061		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
1062		VK_FORMAT_A2R10G10B10_SNORM_PACK32,
1063		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
1064		VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
1065		VK_FORMAT_A2R10G10B10_UINT_PACK32,
1066		VK_FORMAT_A2R10G10B10_SINT_PACK32,
1067		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1068		VK_FORMAT_A2B10G10R10_SNORM_PACK32,
1069		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
1070		VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
1071		VK_FORMAT_A2B10G10R10_UINT_PACK32,
1072		VK_FORMAT_A2B10G10R10_SINT_PACK32,
1073		VK_FORMAT_R16_UNORM,
1074		VK_FORMAT_R16_SNORM,
1075		VK_FORMAT_R16_USCALED,
1076		VK_FORMAT_R16_SSCALED,
1077		VK_FORMAT_R16_UINT,
1078		VK_FORMAT_R16_SINT,
1079		VK_FORMAT_R16_SFLOAT,
1080		VK_FORMAT_R16G16_UNORM,
1081		VK_FORMAT_R16G16_SNORM,
1082		VK_FORMAT_R16G16_USCALED,
1083		VK_FORMAT_R16G16_SSCALED,
1084		VK_FORMAT_R16G16_UINT,
1085		VK_FORMAT_R16G16_SINT,
1086		VK_FORMAT_R16G16_SFLOAT,
1087		VK_FORMAT_R16G16B16_UNORM,
1088		VK_FORMAT_R16G16B16_SNORM,
1089		VK_FORMAT_R16G16B16_USCALED,
1090		VK_FORMAT_R16G16B16_SSCALED,
1091		VK_FORMAT_R16G16B16_UINT,
1092		VK_FORMAT_R16G16B16_SINT,
1093		VK_FORMAT_R16G16B16_SFLOAT,
1094		VK_FORMAT_R16G16B16A16_UNORM,
1095		VK_FORMAT_R16G16B16A16_SNORM,
1096		VK_FORMAT_R16G16B16A16_USCALED,
1097		VK_FORMAT_R16G16B16A16_SSCALED,
1098		VK_FORMAT_R16G16B16A16_UINT,
1099		VK_FORMAT_R16G16B16A16_SINT,
1100		VK_FORMAT_R16G16B16A16_SFLOAT,
1101		VK_FORMAT_R32_UINT,
1102		VK_FORMAT_R32_SINT,
1103		VK_FORMAT_R32_SFLOAT,
1104		VK_FORMAT_R32G32_UINT,
1105		VK_FORMAT_R32G32_SINT,
1106		VK_FORMAT_R32G32_SFLOAT,
1107		VK_FORMAT_R32G32B32_UINT,
1108		VK_FORMAT_R32G32B32_SINT,
1109		VK_FORMAT_R32G32B32_SFLOAT,
1110		VK_FORMAT_R32G32B32A32_UINT,
1111		VK_FORMAT_R32G32B32A32_SINT,
1112		VK_FORMAT_R32G32B32A32_SFLOAT,
1113		VK_FORMAT_R64_UINT,
1114		VK_FORMAT_R64_SINT,
1115		VK_FORMAT_R64_SFLOAT,
1116		VK_FORMAT_R64G64_UINT,
1117		VK_FORMAT_R64G64_SINT,
1118		VK_FORMAT_R64G64_SFLOAT,
1119		VK_FORMAT_R64G64B64_UINT,
1120		VK_FORMAT_R64G64B64_SINT,
1121		VK_FORMAT_R64G64B64_SFLOAT,
1122		VK_FORMAT_R64G64B64A64_UINT,
1123		VK_FORMAT_R64G64B64A64_SINT,
1124		VK_FORMAT_R64G64B64A64_SFLOAT,
1125		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1126		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
1127		VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
1128		VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
1129	};
1130
1131	{
1132		// Check that listing supported modifiers is functional
1133		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "list_modifiers"));
1134		de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "list_modifiers_fmt_features2", "Check that listing supported modifiers is functional with VK_KHR_format_feature_flags2"));
1135
1136		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1137		{
1138			// Check that listing supported modifiers is functional
1139			addFunctionCase(group.get(), getFormatCaseName(formats[formatNdx]), checkModifiersSupported, listModifiersCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>, formats[formatNdx]);
1140			// Check that listing supported modifiers is functional
1141			addFunctionCase(group2.get(), getFormatCaseName(formats[formatNdx]), checkModifiersList2Supported, listModifiersCase<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>, formats[formatNdx]);
1142		}
1143
1144		drmFormatModifiersGroup->addChild(group.release());
1145		drmFormatModifiersGroup->addChild(group2.release());
1146	}
1147
1148	{
1149		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "create_list_modifiers", "Check that creating images with modifier list is functional"));
1150		de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "create_list_modifiers_fmt_features2", "Check that creating images with modifier list is functional with VK_KHR_format_feature_flags2"));
1151
1152		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1153		{
1154			// Check that creating images with modifier list is functional
1155			addFunctionCase(group.get(), getFormatCaseName(formats[formatNdx]), checkModifiersSupported, createImageListModifiersCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>, formats[formatNdx]);
1156			// Check that creating images with modifier list is functional
1157			addFunctionCase(group2.get(), getFormatCaseName(formats[formatNdx]), checkModifiersList2Supported, createImageListModifiersCase<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>, formats[formatNdx]);
1158		}
1159
1160		drmFormatModifiersGroup->addChild(group.release());
1161		drmFormatModifiersGroup->addChild(group2.release());
1162	}
1163
1164	{
1165		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "create_explicit_modifier", "Check that creating images with an explicit modifier is functional"));
1166		de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "create_explicit_modifier_fmt_features2", "Check that creating images with an explicit modifier is functional with VK_KHR_format_feature_flags2"));
1167
1168		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1169		{
1170			// Check that creating images with an explicit modifier is functional
1171			addFunctionCase(group.get(), getFormatCaseName(formats[formatNdx]), checkModifiersSupported, createImageModifierExplicitCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>, formats[formatNdx]);
1172			// Check that creating images with an explicit modifier is functional
1173			addFunctionCase(group2.get(), getFormatCaseName(formats[formatNdx]), checkModifiersList2Supported, createImageModifierExplicitCase<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>, formats[formatNdx]);
1174		}
1175
1176		drmFormatModifiersGroup->addChild(group.release());
1177		drmFormatModifiersGroup->addChild(group2.release());
1178	}
1179
1180	{
1181		de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "export_import", "Test exporting/importing images with modifiers"));
1182		de::MovePtr<tcu::TestCaseGroup> group2(new tcu::TestCaseGroup(testCtx, "export_import_fmt_features2", "Test exporting/importing images with modifiers with VK_KHR_format_feature_flags2"));
1183
1184		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1185		{
1186			// Test exporting/importing images with modifiers
1187			addFunctionCase(group.get(), getFormatCaseName(formats[formatNdx]), checkExportImportExtensions<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>, exportImportMemoryExplicitModifiersCase<VkDrmFormatModifierPropertiesListEXT, VkDrmFormatModifierPropertiesEXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT>, formats[formatNdx]);
1188			// Test exporting/importing images with modifiers
1189			addFunctionCase(group2.get(), getFormatCaseName(formats[formatNdx]), checkExportImportExtensions<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>, exportImportMemoryExplicitModifiersCase<VkDrmFormatModifierPropertiesList2EXT, VkDrmFormatModifierProperties2EXT, VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT>, formats[formatNdx]);
1190		}
1191
1192		drmFormatModifiersGroup->addChild(group.release());
1193		drmFormatModifiersGroup->addChild(group2.release());
1194	}
1195
1196	return drmFormatModifiersGroup.release();
1197}
1198
1199} // modifiers
1200} // vkt
1201