• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  *
6  * Copyright (c) 2022 Khronos Group
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */ /*!
21 * \file
22 * \brief Test for Image Compression control
23 */ /*--------------------------------------------------------------------*/
24 
25 #include <iostream>
26 #include <typeinfo>
27 
28 #include "tcuCommandLine.hpp"
29 #include "tcuDefs.hpp"
30 #include "tcuFunctionLibrary.hpp"
31 #include "tcuPlatform.hpp"
32 #include "tcuResultCollector.hpp"
33 #include "tcuTestCase.hpp"
34 #include "tcuTestLog.hpp"
35 
36 #include "vkApiVersion.hpp"
37 #include "vkDefs.hpp"
38 #include "vkPlatform.hpp"
39 
40 #include "vktApiVersionCheck.hpp"
41 #include "vktCustomInstancesDevices.hpp"
42 #include "vktExternalMemoryUtil.hpp"
43 #include "vktTestCase.hpp"
44 #include "vktTestCaseUtil.hpp"
45 #include "vktTestGroupUtil.hpp"
46 #include "wsi/vktNativeObjectsUtil.hpp"
47 
48 #include "vkDeviceUtil.hpp"
49 #include "vkImageUtil.hpp"
50 #include "vkQueryUtil.hpp"
51 #include "vkRefUtil.hpp"
52 #include "vkWsiUtil.hpp"
53 
54 #include "deString.h"
55 #include "deStringUtil.hpp"
56 
57 #include <map>
58 #include <vector>
59 
60 using namespace vk;
61 using namespace vk::wsi;
62 using namespace std;
63 
64 typedef vector<VkExtensionProperties> Extensions;
65 
66 namespace vkt
67 {
68 
69 namespace api
70 {
71 
72 struct TestParams
73 {
74 	VkFormat					 format;
75 	bool						 useExtension;
76 	VkImageCompressionControlEXT control;
77 	Type						 wsiType;
78 };
79 
checkImageCompressionControlSupport(Context & context,bool swapchain=false)80 static void checkImageCompressionControlSupport(Context& context, bool swapchain = false)
81 {
82 	context.requireDeviceFunctionality("VK_EXT_image_compression_control");
83 	vk::VkPhysicalDeviceImageCompressionControlFeaturesEXT imageCompressionControlFeatures	  = initVulkanStructure();
84 	vk::VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT imageCompressionSwapchain = initVulkanStructure();
85 	vk::VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(&imageCompressionControlFeatures);
86 	if (swapchain)
87 	{
88 		context.requireDeviceFunctionality("VK_EXT_image_compression_control_swapchain");
89 		imageCompressionControlFeatures.pNext = &imageCompressionSwapchain;
90 	}
91 
92 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
93 
94 	if (!imageCompressionControlFeatures.imageCompressionControl)
95 		TCU_THROW(NotSupportedError, "VK_EXT_image_compression_control Image "
96 									 "compression control feature not supported.");
97 	if (swapchain && !imageCompressionSwapchain.imageCompressionControlSwapchain)
98 		TCU_THROW(NotSupportedError, "VK_EXT_image_compression_control_swapchain Image "
99 									 "compression control feature for swapchains not supported.");
100 }
101 
validate(const InstanceInterface & vki,const DeviceInterface & vkd,tcu::ResultCollector & results,VkPhysicalDevice physicalDevice,VkDevice device,TestParams & testParams,VkImage image)102 static void validate(const InstanceInterface& vki, const DeviceInterface& vkd, tcu::ResultCollector& results,
103 					 VkPhysicalDevice physicalDevice, VkDevice device, TestParams& testParams, VkImage image)
104 {
105 	constexpr VkImageAspectFlags planeAspects[]{ VK_IMAGE_ASPECT_PLANE_0_BIT, VK_IMAGE_ASPECT_PLANE_1_BIT,
106 												 VK_IMAGE_ASPECT_PLANE_2_BIT };
107 	const bool isYCbCr   = isYCbCrFormat(testParams.format);
108 	const int  numPlanes = isYCbCr ? getPlaneCount(testParams.format) : 1;
109 	for (int planeIndex = 0; planeIndex < numPlanes; planeIndex++)
110 	{
111 		VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
112 		if (isYCbCr)
113 		{
114 			aspect = planeAspects[planeIndex];
115 		}
116 
117 		VkImageCompressionPropertiesEXT compressionProperties = initVulkanStructure();
118 		VkImageSubresource2EXT			subresource			  = initVulkanStructure();
119 		subresource.imageSubresource.aspectMask				  = aspect;
120 		VkSubresourceLayout2EXT subresourceLayout			  = initVulkanStructure(&compressionProperties);
121 		vkd.getImageSubresourceLayout2EXT(device, image, &subresource, &subresourceLayout);
122 
123 		VkImageCompressionControlEXT compressionEnabled		  = initVulkanStructure();
124 		compressionEnabled.compressionControlPlaneCount		  = testParams.control.compressionControlPlaneCount;
125 		compressionEnabled.flags							  = testParams.control.flags;
126 		VkImageCompressionFixedRateFlagsEXT fixedRateFlags[3] = {
127 			VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT,
128 			VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT,
129 			VK_IMAGE_COMPRESSION_FIXED_RATE_FLAG_BITS_MAX_ENUM_EXT
130 		};
131 
132 		if (compressionEnabled.compressionControlPlaneCount > 0)
133 		{
134 			compressionEnabled.pFixedRateFlags = fixedRateFlags;
135 		}
136 
137 		VkPhysicalDeviceImageFormatInfo2 formatInfo = initVulkanStructure(&compressionEnabled);
138 		formatInfo.format							= testParams.format;
139 		formatInfo.type								= VK_IMAGE_TYPE_2D;
140 		formatInfo.tiling							= VK_IMAGE_TILING_OPTIMAL;
141 		formatInfo.usage							= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
142 
143 		VkImageCompressionPropertiesEXT compressionPropertiesSupported = initVulkanStructure();
144 		VkImageFormatProperties2		properties2 = initVulkanStructure(&compressionPropertiesSupported);
145 
146 		vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &formatInfo, &properties2);
147 
148 		if (testParams.useExtension)
149 		{
150 			if ((compressionPropertiesSupported.imageCompressionFixedRateFlags &
151 				 compressionProperties.imageCompressionFixedRateFlags) !=
152 				compressionProperties.imageCompressionFixedRateFlags)
153 			{
154 				results.fail("Got image with fixed rate flags that are not supported "
155 							 "in image format properties.");
156 			}
157 			if ((compressionPropertiesSupported.imageCompressionFlags & compressionProperties.imageCompressionFlags) !=
158 					compressionProperties.imageCompressionFlags &&
159 				compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
160 			{
161 				results.fail("Got image with compression flags that are not supported "
162 							 "in image format properties.");
163 			}
164 			if (testParams.control.flags == VK_IMAGE_COMPRESSION_DEFAULT_EXT &&
165 				compressionProperties.imageCompressionFixedRateFlags != 0)
166 			{
167 				results.fail("Got lossy compression when DEFAULT compression was requested.");
168 			}
169 			if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
170 				compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT)
171 			{
172 				results.fail("Image compression not disabled.");
173 			}
174 			if (testParams.control.flags == VK_IMAGE_COMPRESSION_DISABLED_EXT &&
175 				compressionProperties.imageCompressionFixedRateFlags != 0)
176 			{
177 				results.fail("Image compression disabled but got fixed rate flags.");
178 			}
179 			if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT &&
180 				!(compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT ||
181 				  compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT ||
182 				  compressionProperties.imageCompressionFlags == VK_IMAGE_COMPRESSION_DEFAULT_EXT))
183 			{
184 				results.fail("Explicit compression flags not returned for image "
185 							 "creation with FIXED RATE DEFAULT.");
186 			}
187 
188 			if (testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT)
189 			{
190 				uint32_t minRequestedRate = 1 << deCtz32(testParams.control.pFixedRateFlags[planeIndex]);
191 				uint32_t actualRate		  = compressionProperties.imageCompressionFixedRateFlags;
192 				if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
193 					compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
194 				{
195 
196 					if (minRequestedRate > actualRate)
197 					{
198 						results.fail("Image created with less bpc than requested.");
199 					}
200 				}
201 			}
202 		}
203 		else
204 		{
205 			if (compressionProperties.imageCompressionFixedRateFlags != VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT)
206 			{
207 				results.fail("Fixed rate compression should not be enabled.");
208 			}
209 
210 			if (compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DISABLED_EXT &&
211 				compressionProperties.imageCompressionFlags != VK_IMAGE_COMPRESSION_DEFAULT_EXT)
212 			{
213 				results.fail("Image compression should be default or not be enabled.");
214 			}
215 		}
216 	}
217 }
218 
checkAhbImageSupport(const Context & context,const TestParams testParams,const deUint32 width,const deUint32 height,const VkImageUsageFlagBits vkUsage)219 static void checkAhbImageSupport (const Context& context, const TestParams testParams, const deUint32 width, const deUint32	height, const VkImageUsageFlagBits vkUsage)
220 {
221 	using namespace vkt::ExternalMemoryUtil;
222 
223 	// Check android hardware buffer can be allocated for the format with usage.
224 	AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
225 	if (!ahbApi)
226 	{
227 		TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
228 	}
229 	deUint64 ahbUsage =  ahbApi->vkUsageToAhbUsage(vkUsage);
230 	{
231 		pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(width,height, 1, ahbApi->vkFormatToAhbFormat(testParams.format), ahbUsage);
232 		if (ahb.internal == DE_NULL)
233 		{
234 			TCU_THROW(NotSupportedError, "Android hardware buffer format not supported");
235 		}
236 	}
237 
238 	// Check external memory supported.
239 	const VkPhysicalDeviceExternalImageFormatInfoKHR external_image_format_info =
240 	{
241 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
242 		&testParams.control,
243 		VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
244 	};
245 
246 	const VkPhysicalDeviceImageFormatInfo2			info				=
247 	{
248 		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
249 		&external_image_format_info,
250 		testParams.format,
251 		VK_IMAGE_TYPE_2D,
252 		VK_IMAGE_TILING_OPTIMAL,
253 		VK_IMAGE_USAGE_SAMPLED_BIT,
254 		0,
255 	};
256 
257 	VkImageCompressionPropertiesEXT compressionPropertiesSupported =
258 	{
259 		VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT,
260 		DE_NULL,
261 		0,
262 		0
263 	};
264 
265 	VkAndroidHardwareBufferUsageANDROID		ahbUsageProperties	=
266 	{
267 		VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
268 		&compressionPropertiesSupported,
269 		0u
270 	};
271 
272 	VkExternalImageFormatProperties					externalProperties	=
273 	{
274 		VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
275 		&ahbUsageProperties,
276 		{ 0u, 0u, 0u }
277 	};
278 
279 	VkImageFormatProperties2						properties			=
280 	{
281 		VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
282 		&externalProperties,
283 		{
284 			{ 0u, 0u, 0u },
285 			0u,
286 			0u,
287 			0u,
288 			0u
289 		}
290 	};
291 
292 	VkResult result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &info, &properties);
293 
294 	if(result == VK_ERROR_FORMAT_NOT_SUPPORTED)
295 		TCU_THROW(NotSupportedError, "Format not supported");
296 
297 	if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
298 		TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
299 
300 	if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0)
301 		TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
302 
303 	if((compressionPropertiesSupported.imageCompressionFlags == VK_IMAGE_COMPRESSION_DISABLED_EXT)
304 		&& (testParams.control.flags != VK_IMAGE_COMPRESSION_DISABLED_EXT))
305 	{
306 		TCU_THROW(NotSupportedError, "Compression is disbaled, and other compression flags are not supported");
307 	}
308 
309 	if((ahbUsageProperties.androidHardwareBufferUsage & ahbUsage) != ahbUsage)
310 	{
311 		TCU_THROW(NotSupportedError, "Android hardware buffer usage is not supported");
312 	}
313 }
314 
ahbImageCreateTest(Context & context,TestParams testParams)315 static tcu::TestStatus ahbImageCreateTest(Context& context, TestParams testParams)
316 {
317 	using namespace vkt::ExternalMemoryUtil;
318 
319 	context.requireDeviceFunctionality("VK_ANDROID_external_memory_android_hardware_buffer");
320 	context.requireDeviceFunctionality("VK_EXT_image_compression_control");
321 
322 	const deUint32			   width			= 32;
323 	const deUint32			   height			= 32;
324 	deUint32				   queueFamilyIndex = context.getUniversalQueueFamilyIndex();
325 	const vk::DeviceInterface& vkd				= context.getDeviceInterface();
326 	VkDevice				   device			= context.getDevice();
327 	tcu::TestLog&			   log				= context.getTestContext().getLog();
328 	tcu::ResultCollector	   results(log);
329 	const VkImageUsageFlagBits vkUsage			= VK_IMAGE_USAGE_SAMPLED_BIT;
330 	const bool				   is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
331 	const uint32_t			   numPlanes		= isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
332 
333 	testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
334 
335 	VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
336 
337 	for (unsigned i{}; i < (is_fixed_rate_ex ? 24 : 1); i++)
338 	{
339 		planeFlags[0] ^= 3 << i;
340 		planeFlags[1] ^= 5 << i;
341 		planeFlags[2] ^= 7 << i;
342 
343 		if (is_fixed_rate_ex)
344 		{
345 			testParams.control.compressionControlPlaneCount = numPlanes;
346 			testParams.control.pFixedRateFlags = planeFlags;
347 		}
348 
349 		const vk::VkExternalMemoryImageCreateInfo externalCreateInfo = {
350 			vk::VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, &testParams.control,
351 			VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
352 		};
353 		const vk::VkImageCreateInfo createInfo = { vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
354 												   &externalCreateInfo,
355 												   0,
356 												   vk::VK_IMAGE_TYPE_2D,
357 												   testParams.format,
358 												   {
359 													   width,
360 													   height,
361 													   1u,
362 												   },
363 												   1,
364 												   1,
365 												   vk::VK_SAMPLE_COUNT_1_BIT,
366 												   VK_IMAGE_TILING_OPTIMAL,
367 												   vkUsage,
368 												   vk::VK_SHARING_MODE_EXCLUSIVE,
369 												   1,
370 												   &queueFamilyIndex,
371 												   vk::VK_IMAGE_LAYOUT_UNDEFINED };
372 
373 		checkAhbImageSupport(context, testParams, width, height, vkUsage);
374 
375 		Move<VkImage>			   image		= vk::createImage(vkd, device, &createInfo);
376 		const VkMemoryRequirements requirements = ExternalMemoryUtil::getImageMemoryRequirements(
377 			vkd, device, image.get(), VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID);
378 		const deUint32		 exportedMemoryTypeIndex(ExternalMemoryUtil::chooseMemoryType(requirements.memoryTypeBits));
379 		Move<VkDeviceMemory> memory = ExternalMemoryUtil::allocateExportableMemory(
380 			vkd, device, requirements.size, exportedMemoryTypeIndex,
381 			VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, image.get());
382 
383 		VK_CHECK(vkd.bindImageMemory(device, image.get(), memory.get(), 0u));
384 		validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
385 				 context.getDevice(), testParams, image.get());
386 	}
387 	return tcu::TestStatus(results.getResult(), results.getMessage());
388 }
389 
imageCreateTest(Context & context,TestParams testParams)390 static tcu::TestStatus imageCreateTest(Context& context, TestParams testParams)
391 {
392 	checkImageCompressionControlSupport(context);
393 	deUint32			 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
394 	const VkDevice		 device			  = context.getDevice();
395 	VkExtent3D			 extent			  = { 16, 16, 1 };
396 	tcu::TestLog&		 log			  = context.getTestContext().getLog();
397 	tcu::ResultCollector results(log);
398 	const bool			 is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
399 
400 	VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
401 
402 	for (unsigned i{}; i < (is_fixed_rate_ex ? 24 : 1); i++)
403 	{
404 		planeFlags[0] ^= 3 << i;
405 		planeFlags[1] ^= 5 << i;
406 		planeFlags[2] ^= 7 << i;
407 
408 		if (is_fixed_rate_ex)
409 		{
410 			testParams.control.pFixedRateFlags = planeFlags;
411 		}
412 
413 		VkImageCreateInfo imageCreateInfo = {
414 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
415 			DE_NULL,							 // const void*                  pNext;
416 			0,									 // VkImageCreateFlags   flags;
417 			VK_IMAGE_TYPE_2D,					 // VkImageType
418 			testParams.format,					 // VkFormat format;
419 			extent,								 // VkExtent3D extent;
420 			1u,									 // deUint32                             mipLevels;
421 			1u,									 // deUint32 arraySize;
422 			VK_SAMPLE_COUNT_1_BIT,				 // deUint32 samples;
423 			VK_IMAGE_TILING_OPTIMAL,			 // VkImageTiling                tiling;
424 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, // VkImageUsageFlags    usage;
425 			VK_SHARING_MODE_EXCLUSIVE,			 // VkSharingMode sharingMode;
426 			1u,									 // deUint32                             queueFamilyCount;
427 			&queueFamilyIndex,					 // const deUint32* pQueueFamilyIndices;
428 			VK_IMAGE_LAYOUT_UNDEFINED,			 // VkImageLayout initialLayout;
429 		};
430 
431 		if (testParams.useExtension)
432 		{
433 			imageCreateInfo.pNext = &testParams.control;
434 		}
435 
436 		checkImageSupport(context.getInstanceInterface(), context.getPhysicalDevice(), imageCreateInfo);
437 
438 		Move<VkImage> image = createImage(context.getDeviceInterface(), device, &imageCreateInfo);
439 
440 		validate(context.getInstanceInterface(), context.getDeviceInterface(), results, context.getPhysicalDevice(),
441 				 context.getDevice(), testParams, image.get());
442 	}
443 	return tcu::TestStatus(results.getResult(), results.getMessage());
444 }
445 
addImageCompressionControlTests(tcu::TestCaseGroup * group,TestParams testParams)446 void addImageCompressionControlTests(tcu::TestCaseGroup* group, TestParams testParams)
447 {
448 	const bool is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
449 
450 	static const struct
451 	{
452 		VkFormat begin;
453 		VkFormat end;
454 	} s_formatRanges[] = {
455 		// core formats
456 		{ (VkFormat)(VK_FORMAT_UNDEFINED + 1), VK_CORE_FORMAT_LAST },
457 
458 		// YCbCr formats
459 		{ VK_FORMAT_G8B8G8R8_422_UNORM, (VkFormat)(VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM + 1) },
460 
461 		// YCbCr extended formats
462 		{ VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, (VkFormat)(VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT + 1) },
463 	};
464 
465 	for (int rangeNdx = 0; rangeNdx < DE_LENGTH_OF_ARRAY(s_formatRanges); ++rangeNdx)
466 	{
467 		const VkFormat rangeBegin = s_formatRanges[rangeNdx].begin;
468 		const VkFormat rangeEnd	  = s_formatRanges[rangeNdx].end;
469 
470 		for (testParams.format = rangeBegin; testParams.format != rangeEnd;
471 			 testParams.format = (VkFormat)(testParams.format + 1))
472 		{
473 			if (isCompressedFormat(testParams.format))
474 				continue;
475 
476 			const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
477 			testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
478 
479 			const char* const enumName = getFormatName(testParams.format);
480 			const string	  caseName = de::toLower(string(enumName).substr(10));
481 			addFunctionCase(group, caseName, enumName, imageCreateTest, testParams);
482 		}
483 	}
484 }
485 
createInstanceWithWsi(Context & context,Type wsiType,const vector<string> extraExtensions,const VkAllocationCallbacks * pAllocator=DE_NULL)486 CustomInstance createInstanceWithWsi(Context& context, Type wsiType, const vector<string> extraExtensions,
487 									 const VkAllocationCallbacks* pAllocator = DE_NULL)
488 {
489 	const deUint32 version	  = context.getUsedApiVersion();
490 	vector<string> extensions = extraExtensions;
491 
492 	extensions.push_back("VK_KHR_surface");
493 	extensions.push_back(getExtensionName(wsiType));
494 	extensions.push_back("VK_KHR_get_surface_capabilities2");
495 
496 	vector<string> instanceExtensions;
497 	for (const auto& ext : extensions)
498 	{
499 		if (!context.isInstanceFunctionalitySupported(ext))
500 			TCU_THROW(NotSupportedError, (ext + " is not supported").c_str());
501 
502 		if (!isCoreInstanceExtension(version, ext))
503 			instanceExtensions.push_back(ext);
504 	}
505 
506 	return vkt::createCustomInstanceWithExtensions(context, instanceExtensions, pAllocator);
507 }
508 struct InstanceHelper
509 {
510 	const vector<VkExtensionProperties> supportedExtensions;
511 	CustomInstance						instance;
512 	const InstanceDriver&				vki;
513 
InstanceHelpervkt::api::InstanceHelper514 	InstanceHelper(Context& context, Type wsiType, const VkAllocationCallbacks* pAllocator = DE_NULL)
515 		: supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
516 		, instance(createInstanceWithWsi(context, wsiType, vector<string>(), pAllocator))
517 		, vki(instance.getDriver())
518 	{
519 	}
520 
InstanceHelpervkt::api::InstanceHelper521 	InstanceHelper(Context& context, Type wsiType, const vector<string>& extensions,
522 				   const VkAllocationCallbacks* pAllocator = DE_NULL)
523 		: supportedExtensions(enumerateInstanceExtensionProperties(context.getPlatformInterface(), DE_NULL))
524 		, instance(createInstanceWithWsi(context, wsiType, extensions, pAllocator))
525 		, vki(instance.getDriver())
526 	{
527 	}
528 };
529 
createDeviceWithWsi(const PlatformInterface & vkp,deUint32 apiVersion,VkInstance instance,const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const Extensions & supportedExtensions,const vector<string> & additionalExtensions,deUint32 queueFamilyIndex,bool validationEnabled,const VkAllocationCallbacks * pAllocator=DE_NULL)530 Move<VkDevice> createDeviceWithWsi(const PlatformInterface& vkp, deUint32 apiVersion, VkInstance instance,
531 								   const InstanceInterface& vki, VkPhysicalDevice physicalDevice,
532 								   const Extensions& supportedExtensions, const vector<string>& additionalExtensions,
533 								   deUint32 queueFamilyIndex, bool validationEnabled,
534 								   const VkAllocationCallbacks* pAllocator = DE_NULL)
535 {
536 	const float					  queuePriorities[] = { 1.0f };
537 	const VkDeviceQueueCreateInfo queueInfo			= {
538 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
539 		nullptr,
540 		(VkDeviceQueueCreateFlags)0,
541 		queueFamilyIndex,
542 		DE_LENGTH_OF_ARRAY(queuePriorities),
543 		&queuePriorities[0],
544 	};
545 
546 	vector<string> extensions;
547 	extensions.push_back("VK_KHR_swapchain");
548 	extensions.push_back("VK_EXT_image_compression_control");
549 	extensions.push_back("VK_EXT_image_compression_control_swapchain");
550 	extensions.insert(end(extensions), begin(additionalExtensions), end(additionalExtensions));
551 
552 	for (const auto& extName : extensions)
553 	{
554 		if (!isCoreDeviceExtension(apiVersion, extName) &&
555 			!isExtensionStructSupported(supportedExtensions, RequiredExtension(extName)))
556 			TCU_THROW(NotSupportedError, extName + " is not supported");
557 	}
558 
559 	vk::VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT imageCompressionSwapchain = initVulkanStructure();
560 	imageCompressionSwapchain.imageCompressionControlSwapchain = VK_TRUE;
561 
562 	const VkPhysicalDeviceFeatures features = {};
563 
564 	// Convert from std::vector<std::string> to std::vector<const char*>.
565 	std::vector<const char*> extensionsChar;
566 	extensionsChar.reserve(extensions.size());
567 	std::transform(begin(extensions), end(extensions), std::back_inserter(extensionsChar),
568 				   [](const std::string& s) { return s.c_str(); });
569 
570 	const VkDeviceCreateInfo deviceParams = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
571 											  &imageCompressionSwapchain,
572 											  (VkDeviceCreateFlags)0,
573 											  1u,
574 											  &queueInfo,
575 											  0u,											// enabledLayerCount
576 											  nullptr,										// ppEnabledLayerNames
577 											  static_cast<deUint32>(extensionsChar.size()), // enabledExtensionCount
578 											  extensionsChar.data(),						// ppEnabledExtensionNames
579 											  &features };
580 
581 	return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceParams, pAllocator);
582 }
583 
584 struct DeviceHelper
585 {
586 	const VkPhysicalDevice physicalDevice;
587 	const deUint32		   queueFamilyIndex;
588 	const Unique<VkDevice> device;
589 	const DeviceDriver	   vkd;
590 	const VkQueue		   queue;
591 
DeviceHelpervkt::api::DeviceHelper592 	DeviceHelper(Context& context, const InstanceInterface& vki, VkInstance instance,
593 				 const vector<VkSurfaceKHR>& surface, const vector<string>& additionalExtensions = vector<string>(),
594 				 const VkAllocationCallbacks* pAllocator = DE_NULL)
595 		: physicalDevice(chooseDevice(vki, instance, context.getTestContext().getCommandLine()))
596 		, queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, surface))
597 		, device(createDeviceWithWsi(context.getPlatformInterface(), context.getUsedApiVersion(), instance, vki,
598 									 physicalDevice, enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL),
599 									 additionalExtensions, queueFamilyIndex,
600 									 context.getTestContext().getCommandLine().isValidationEnabled(), pAllocator))
601 		, vkd(context.getPlatformInterface(), instance, *device)
602 		, queue(getDeviceQueue(vkd, *device, queueFamilyIndex, 0))
603 	{
604 	}
605 
606 	// Single-surface shortcut.
DeviceHelpervkt::api::DeviceHelper607 	DeviceHelper(Context& context, const InstanceInterface& vki, VkInstance instance, VkSurfaceKHR surface,
608 				 const vector<string>&		  additionalExtensions = vector<string>(),
609 				 const VkAllocationCallbacks* pAllocator		   = DE_NULL)
610 		: DeviceHelper(context, vki, instance, vector<VkSurfaceKHR>(1u, surface), additionalExtensions, pAllocator)
611 	{
612 	}
613 };
swapchainCreateTest(Context & context,TestParams testParams)614 static tcu::TestStatus swapchainCreateTest(Context& context, TestParams testParams)
615 {
616 	checkImageCompressionControlSupport(context, true);
617 
618 	tcu::TestLog&		 log = context.getTestContext().getLog();
619 	tcu::ResultCollector results(log);
620 
621 	const InstanceHelper	 instHelper(context, testParams.wsiType);
622 	const wsi::NativeObjects native(context, instHelper.supportedExtensions, testParams.wsiType);
623 	const bool				 is_fixed_rate_ex = testParams.control.flags == VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT;
624 
625 	VkExtent2D							extent2d = { 16, 16 };
626 	VkImageCompressionFixedRateFlagsEXT planeFlags[3]{};
627 
628 	for (unsigned i{}; i < (is_fixed_rate_ex ? 24 : 1); i++)
629 	{
630 		planeFlags[0] ^= 3 << i;
631 
632 		if (is_fixed_rate_ex)
633 		{
634 			testParams.control.pFixedRateFlags = planeFlags;
635 		}
636 
637 		const Unique<VkSurfaceKHR> surface(createSurface(instHelper.vki, instHelper.instance, testParams.wsiType,
638 														 native.getDisplay(), native.getWindow(),
639 														 context.getTestContext().getCommandLine()));
640 
641 		const DeviceHelper devHelper(context, instHelper.vki, instHelper.instance, *surface, vector<string>());
642 
643 		VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = initVulkanStructure();
644 		VkSurfaceCapabilities2KHR		caps		= initVulkanStructure();
645 		surfaceInfo.surface							= surface.get();
646 
647 		instHelper.vki.getPhysicalDeviceSurfaceCapabilities2KHR(devHelper.physicalDevice, &surfaceInfo, &caps);
648 
649 		deUint32 numFormats;
650 		instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
651 														   nullptr);
652 
653 		vector<VkSurfaceFormat2KHR> formats(numFormats);
654 		for (auto& surfaceFormat : formats)
655 		{
656 			surfaceFormat = initVulkanStructure();
657 		}
658 
659 		instHelper.vki.getPhysicalDeviceSurfaceFormats2KHR(devHelper.physicalDevice, &surfaceInfo, &numFormats,
660 														   formats.data());
661 
662 		deUint32 queueFamilyIndex = devHelper.queueFamilyIndex;
663 
664 		for (auto& format : formats)
665 		{
666 			testParams.format = format.surfaceFormat.format;
667 
668 			const uint32_t numPlanes = isYCbCrFormat(testParams.format) ? getPlaneCount(testParams.format) : 1;
669 			testParams.control.compressionControlPlaneCount = is_fixed_rate_ex ? numPlanes : 0;
670 
671 			VkSwapchainCreateInfoKHR swapchainInfo = initVulkanStructure();
672 			swapchainInfo.surface				   = surface.get();
673 			swapchainInfo.minImageCount			   = caps.surfaceCapabilities.minImageCount;
674 			swapchainInfo.imageFormat			   = format.surfaceFormat.format;
675 			swapchainInfo.imageColorSpace		   = format.surfaceFormat.colorSpace;
676 			swapchainInfo.imageExtent			   = extent2d;
677 			swapchainInfo.imageArrayLayers		   = 1;
678 			swapchainInfo.imageUsage			   = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
679 			swapchainInfo.imageSharingMode		   = VK_SHARING_MODE_EXCLUSIVE;
680 			swapchainInfo.queueFamilyIndexCount	   = 1;
681 			swapchainInfo.pQueueFamilyIndices	   = &queueFamilyIndex;
682 			swapchainInfo.preTransform			   = caps.surfaceCapabilities.currentTransform;
683 			swapchainInfo.compositeAlpha		   = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
684 			swapchainInfo.presentMode			   = VK_PRESENT_MODE_FIFO_KHR;
685 			swapchainInfo.clipped				   = VK_TRUE;
686 
687 			swapchainInfo.pNext = &testParams.control;
688 
689 			Move<VkSwapchainKHR> swapchain = createSwapchainKHR(devHelper.vkd, devHelper.device.get(), &swapchainInfo);
690 
691 			deUint32 imageCount = 0;
692 			devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, nullptr);
693 			vector<VkImage> images(imageCount);
694 			devHelper.vkd.getSwapchainImagesKHR(devHelper.device.get(), swapchain.get(), &imageCount, images.data());
695 
696 			validate(instHelper.vki, devHelper.vkd, results, devHelper.physicalDevice, devHelper.device.get(),
697 					 testParams, images[0]);
698 		}
699 	}
700 
701 	return tcu::TestStatus(results.getResult(), results.getMessage());
702 }
703 
addAhbCompressionControlTests(tcu::TestCaseGroup * group,TestParams testParams)704 void addAhbCompressionControlTests(tcu::TestCaseGroup *group, TestParams testParams)
705 {
706 	// Ahb formats
707 	static const vk::VkFormat ahbFormats[] = {
708 		VK_FORMAT_R8G8B8A8_UNORM,
709 		VK_FORMAT_R8G8B8_UNORM,
710 		VK_FORMAT_R5G6B5_UNORM_PACK16,
711 		VK_FORMAT_R16G16B16A16_SFLOAT,
712 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
713 		VK_FORMAT_D16_UNORM,
714 		VK_FORMAT_X8_D24_UNORM_PACK32,
715 		VK_FORMAT_D24_UNORM_S8_UINT,
716 		VK_FORMAT_D32_SFLOAT,
717 		VK_FORMAT_D32_SFLOAT_S8_UINT,
718 		VK_FORMAT_S8_UINT
719 	};
720 
721 	for (int index = 0; index < DE_LENGTH_OF_ARRAY(ahbFormats); ++index)
722 	{
723 		testParams.format = ahbFormats[index];
724 		const char *const enumName = getFormatName(testParams.format);
725 		const string caseName = de::toLower(string(enumName).substr(10));
726 		addFunctionCase(group, caseName, enumName, ahbImageCreateTest, testParams);
727 	}
728 }
729 
createImageCompressionControlTests(tcu::TestContext & testCtx)730 tcu::TestCaseGroup* createImageCompressionControlTests(tcu::TestContext& testCtx)
731 {
732 	de::MovePtr<tcu::TestCaseGroup> group(
733 		new tcu::TestCaseGroup(testCtx, "image_compression_control", "Test for image compression control."));
734 
735 	TestParams			testParams{};
736 	tcu::TestCaseGroup* subgroup(
737 		new tcu::TestCaseGroup(testCtx, "create_image", "Test creating images with compression control struct"));
738 
739 	subgroup->addChild(createTestGroup(testCtx, "no_compression_control",
740 									   "Queries images created without compression control struct.",
741 									   addImageCompressionControlTests, testParams));
742 
743 	testParams.useExtension	 = true;
744 	testParams.control		 = initVulkanStructure();
745 	testParams.control.flags = VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT;
746 
747 	struct
748 	{
749 		const char*				   name;
750 		VkImageCompressionFlagsEXT flag;
751 	} constexpr compression_flags[] = {
752 		{ "default", VK_IMAGE_COMPRESSION_DEFAULT_EXT },
753 		{ "fixed_rate_default", VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT },
754 		{ "disabled", VK_IMAGE_COMPRESSION_DISABLED_EXT },
755 		{ "explicit", VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT },
756 	};
757 
758 	for (auto& flag : compression_flags)
759 	{
760 		testParams.control.flags = flag.flag;
761 		subgroup->addChild(createTestGroup(testCtx, flag.name,
762 										   "Queries images created with compression control struct.",
763 										   addImageCompressionControlTests, testParams));
764 	}
765 	group->addChild(subgroup);
766 
767 	subgroup = new tcu::TestCaseGroup(testCtx, "android_hardware_buffer",
768 									  "Test creating Android Hardware buffer with compression control struct");
769 
770 	for (auto& flag : compression_flags)
771 	{
772 		testParams.control.flags = flag.flag;
773 		subgroup->addChild(createTestGroup(testCtx, flag.name,
774 										   "Queries images created with compression control struct.",
775 										   addAhbCompressionControlTests, testParams));
776 	}
777 
778 	group->addChild(subgroup);
779 
780 	subgroup = new tcu::TestCaseGroup(testCtx, "swapchain", "swapchain");
781 	for (int typeNdx = 0; typeNdx < vk::wsi::TYPE_LAST; ++typeNdx)
782 	{
783 		const vk::wsi::Type wsiType = (vk::wsi::Type)typeNdx;
784 		testParams.wsiType			= wsiType;
785 
786 		tcu::TestCaseGroup* wsi_subgroup(new tcu::TestCaseGroup(testCtx, getName(wsiType), "Swapchain tests"));
787 
788 		for (auto& flag : compression_flags)
789 		{
790 			testParams.control.flags = flag.flag;
791 			addFunctionCase(wsi_subgroup, flag.name, flag.name, swapchainCreateTest, testParams);
792 		}
793 		subgroup->addChild(wsi_subgroup);
794 	}
795 
796 	group->addChild(subgroup);
797 
798 	return group.release();
799 }
800 
801 } // namespace api
802 
803 } // namespace vkt
804