• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
51 namespace vkt
52 {
53 namespace modifiers
54 {
55 namespace
56 {
57 using namespace vk;
58 using tcu::UVec2;
59 using tcu::TestLog;
60 
61 struct ExplicitModifier
62 {
63 	uint64_t				modifier;
64 	uint32_t				modifierPlaneCount;
65 	VkSubresourceLayout*	pPlaneLayouts;
66 };
67 
checkModifiersSupported(Context & context,VkFormat format)68 void 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 
checkModifiersList2Supported(Context & context,VkFormat fmt)88 void 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 
getFormatCaseName(VkFormat format)96 std::string getFormatCaseName (VkFormat format)
97 {
98 	return de::toLower(de::toString(getFormatStr(format)).substr(10));
99 }
100 
101 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
getDrmFormatModifiers(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkFormat format)102 std::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.
verifyHandleTypeForFormatModifier(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const VkFormat format,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags handleType,const deUint64 drmFormatModifier)128 bool 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 
176 template <typename FlagsType>
featuresCompatible(FlagsType modifierFeatures,VkFormatFeatureFlags testFeatures)177 static 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 
186 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
getExportImportCompatibleModifiers(Context & context,VkFormat format)187 std::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 
225 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
checkExportImportExtensions(Context & context,VkFormat format)226 void 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 
isModifierCompatibleWithImageProperties(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const VkFormat * formats,const deUint32 nFormats,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags handleType,const deUint64 drmFormatModifier,VkImageFormatProperties2 & imageProperties)264 deBool 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 
323 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
listModifiersCase(Context & context,VkFormat format)324 tcu::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 
createImageNoModifiers(const DeviceInterface & vkd,const VkDevice device,const VkImageUsageFlags imageUsages,const VkFormat format,const UVec2 & size)365 Move<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 
createImageWithDrmFormatExplicitModifier(const DeviceInterface & vkd,const VkDevice device,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags externalMemoryHandleTypeFlags,const std::vector<VkFormat> & formats,const UVec2 & size,const ExplicitModifier drmFormatModifier)393 Move<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 
createImageWithDrmFormatModifiers(const DeviceInterface & vkd,const VkDevice device,const VkImageType imageType,const VkImageUsageFlags imageUsages,const VkExternalMemoryHandleTypeFlags externalMemoryHandleTypeFlags,const std::vector<VkFormat> & formats,const UVec2 & size,const std::vector<deUint64> & drmFormatModifiers)454 Move<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 
514 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
createImageListModifiersCase(Context & context,const VkFormat format)515 tcu::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 
569 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
createImageModifierExplicitCase(Context & context,const VkFormat format)570 tcu::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 
chooseMemoryType(deUint32 bits)662 deUint32 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 
676 template <typename ModifierProps>
exportImportMemoryExplicitModifiersCase(Context & context,const VkFormat format,const ModifierProps & modifier)677 bool 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 
974 template <typename ModifierList, typename ModifierProps, VkStructureType modifierListSType>
exportImportMemoryExplicitModifiersCase(Context & context,const VkFormat format)975 tcu::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 
createTests(tcu::TestContext & testCtx,const std::string & name)993 tcu::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