Home | History | Annotate | Download | only in pipeline
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Imagination Technologies Ltd.
      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 Image View Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktPipelineImageViewTests.hpp"
     26 #include "vktPipelineImageSamplingInstance.hpp"
     27 #include "vktPipelineImageUtil.hpp"
     28 #include "vktPipelineVertexUtil.hpp"
     29 #include "vktTestCase.hpp"
     30 #include "vkImageUtil.hpp"
     31 #include "vkPrograms.hpp"
     32 #include "tcuPlatform.hpp"
     33 #include "tcuTextureUtil.hpp"
     34 #include "deStringUtil.hpp"
     35 #include "deMemory.h"
     36 
     37 #include <sstream>
     38 #include <vector>
     39 
     40 namespace vkt
     41 {
     42 namespace pipeline
     43 {
     44 
     45 using namespace vk;
     46 using de::MovePtr;
     47 
     48 namespace
     49 {
     50 
     51 
     52 class ImageViewTest : public vkt::TestCase
     53 {
     54 public:
     55 							ImageViewTest			(tcu::TestContext&				testContext,
     56 													 const char*					name,
     57 													 const char*					description,
     58 													 VkImageViewType				imageViewType,
     59 													 VkFormat						imageFormat,
     60 													 float							samplerLod,
     61 													 const VkComponentMapping&		componentMapping,
     62 													 const VkImageSubresourceRange&	subresourceRange);
     63 	virtual					~ImageViewTest			(void) {}
     64 
     65 	virtual void			initPrograms			(SourceCollections&				sourceCollections) const;
     66 	virtual TestInstance*	createInstance			(Context&						context) const;
     67 	static std::string		getGlslSamplerType		(const tcu::TextureFormat&		format,
     68 													 VkImageViewType				type);
     69 	static tcu::UVec2		getRenderSize			(VkImageViewType				viewType);
     70 	static tcu::IVec3		getImageSize			(VkImageViewType				viewType);
     71 	static int				getArraySize			(VkImageViewType				viewType);
     72 	static int				getNumLevels			(VkImageViewType				viewType);
     73 	static tcu::Vec4		swizzle					(tcu::Vec4						inputData,
     74 													 VkComponentMapping				componentMapping);
     75 private:
     76 	VkImageViewType			m_imageViewType;
     77 	VkFormat				m_imageFormat;
     78 	float					m_samplerLod;
     79 	VkComponentMapping		m_componentMapping;
     80 	VkImageSubresourceRange	m_subresourceRange;
     81 };
     82 
     83 ImageViewTest::ImageViewTest (tcu::TestContext&					testContext,
     84 							  const char*						name,
     85 							  const char*						description,
     86 							  VkImageViewType					imageViewType,
     87 							  VkFormat							imageFormat,
     88 							  float								samplerLod,
     89 							  const VkComponentMapping&			componentMapping,
     90 							  const VkImageSubresourceRange&	subresourceRange)
     91 
     92 	: vkt::TestCase			(testContext, name, description)
     93 	, m_imageViewType		(imageViewType)
     94 	, m_imageFormat			(imageFormat)
     95 	, m_samplerLod			(samplerLod)
     96 	, m_componentMapping	(componentMapping)
     97 	, m_subresourceRange	(subresourceRange)
     98 {
     99 }
    100 
    101 tcu::Vec4 ImageViewTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping)
    102 {
    103 	// array map with enum VkComponentSwizzle
    104 	const float channelValues[] =
    105 	{
    106 		-1.0f,
    107 		0.0f,
    108 		1.0f,
    109 		inputData.x(),
    110 		inputData.y(),
    111 		inputData.z(),
    112 		inputData.w(),
    113 		-1.0f
    114 	};
    115 
    116 	return tcu::Vec4(channelValues[componentMapping.r],
    117 					 channelValues[componentMapping.g],
    118 					 channelValues[componentMapping.b],
    119 					 channelValues[componentMapping.a]);
    120 }
    121 
    122 void ImageViewTest::initPrograms (SourceCollections& sourceCollections) const
    123 {
    124 	std::ostringstream				vertexSrc;
    125 	std::ostringstream				fragmentSrc;
    126 	const char*						texCoordSwizzle	= DE_NULL;
    127 	const tcu::TextureFormat		format			= (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
    128 																						  : mapVkFormat(m_imageFormat);
    129 
    130 	tcu::Vec4						lookupScale;
    131 	tcu::Vec4						lookupBias;
    132 
    133 	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
    134 
    135 	tcu::Vec4						swizzledScale	= swizzle(lookupScale, m_componentMapping);
    136 	tcu::Vec4						swizzledBias	= swizzle(lookupBias, m_componentMapping);
    137 
    138 	switch (m_imageViewType)
    139 	{
    140 		case VK_IMAGE_VIEW_TYPE_1D:
    141 			texCoordSwizzle = "x";
    142 			break;
    143 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
    144 		case VK_IMAGE_VIEW_TYPE_2D:
    145 			texCoordSwizzle = "xy";
    146 			break;
    147 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
    148 		case VK_IMAGE_VIEW_TYPE_3D:
    149 		case VK_IMAGE_VIEW_TYPE_CUBE:
    150 			texCoordSwizzle = "xyz";
    151 			break;
    152 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
    153 			texCoordSwizzle = "xyzw";
    154 			break;
    155 		default:
    156 			DE_ASSERT(false);
    157 			break;
    158 	}
    159 
    160 	vertexSrc << "#version 440\n"
    161 			  << "layout(location = 0) in vec4 position;\n"
    162 			  << "layout(location = 1) in vec4 texCoords;\n"
    163 			  << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
    164 			  << "out gl_PerVertex {\n"
    165 			  << "	vec4 gl_Position;\n"
    166 			  << "};\n"
    167 			  << "void main (void)\n"
    168 			  << "{\n"
    169 			  << "	gl_Position = position;\n"
    170 			  << "	vtxTexCoords = texCoords;\n"
    171 			  << "}\n";
    172 
    173 	fragmentSrc << "#version 440\n"
    174 				<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
    175 				<< "layout(location = 0) in highp vec4 vtxTexCoords;\n"
    176 				<< "layout(location = 0) out highp vec4 fragColor;\n"
    177 				<< "void main (void)\n"
    178 				<< "{\n"
    179 				<< "	fragColor = ";
    180 
    181 	if (m_samplerLod > 0.0f)
    182 		fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ")";
    183 	else
    184 		fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
    185 
    186 	fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
    187 				<< "}\n";
    188 
    189 	sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
    190 	sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
    191 }
    192 
    193 TestInstance* ImageViewTest::createInstance (Context& context) const
    194 {
    195 	const tcu::UVec2				renderSize		= getRenderSize(m_imageViewType);
    196 	const tcu::IVec3				imageSize		= getImageSize(m_imageViewType);
    197 	const int						arraySize		= getArraySize(m_imageViewType);
    198 	const std::vector<Vertex4Tex4>	vertices		= createTestQuadMosaic(m_imageViewType);
    199 
    200 	const VkSamplerCreateInfo		samplerParams	=
    201 	{
    202 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,									// VkStructureType			sType;
    203 		DE_NULL,																// const void*				pNext;
    204 		0u,																		// VkSamplerCreateFlags		flags;
    205 		VK_FILTER_NEAREST,														// VkFilter					magFilter;
    206 		VK_FILTER_NEAREST,														// VkFilter					minFilter;
    207 		VK_SAMPLER_MIPMAP_MODE_NEAREST,											// VkSamplerMipmapMode		mipmapMode;
    208 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,									// VkSamplerAddressMode		addressModeU;
    209 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,									// VkSamplerAddressMode		addressModeV;
    210 		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,									// VkSamplerAddressMode		addressModeW;
    211 		0.0f,																	// float					mipLodBias;
    212 		VK_FALSE,																// VkBool32					anisotropyEnable;
    213 		1.0f,																	// float					maxAnisotropy;
    214 		false,																	// VkBool32					compareEnable;
    215 		VK_COMPARE_OP_NEVER,													// VkCompareOp				compareOp;
    216 		0.0f,																	// float					minLod;
    217 		(float)(m_subresourceRange.levelCount - 1),								// float					maxLod;
    218 		getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat),	// VkBorderColor			borderColor;
    219 		false																	// VkBool32					unnormalizedCoordinates;
    220 	};
    221 
    222 	return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat, imageSize, arraySize, m_componentMapping, m_subresourceRange, samplerParams, m_samplerLod, vertices);
    223 }
    224 
    225 std::string ImageViewTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
    226 {
    227 	std::ostringstream samplerType;
    228 
    229 	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
    230 		samplerType << "u";
    231 	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
    232 		samplerType << "i";
    233 
    234 	switch (type)
    235 	{
    236 		case VK_IMAGE_VIEW_TYPE_1D:
    237 			samplerType << "sampler1D";
    238 			break;
    239 
    240 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
    241 			samplerType << "sampler1DArray";
    242 			break;
    243 
    244 		case VK_IMAGE_VIEW_TYPE_2D:
    245 			samplerType << "sampler2D";
    246 			break;
    247 
    248 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
    249 			samplerType << "sampler2DArray";
    250 			break;
    251 
    252 		case VK_IMAGE_VIEW_TYPE_3D:
    253 			samplerType << "sampler3D";
    254 			break;
    255 
    256 		case VK_IMAGE_VIEW_TYPE_CUBE:
    257 			samplerType << "samplerCube";
    258 			break;
    259 
    260 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
    261 			samplerType << "samplerCubeArray";
    262 			break;
    263 
    264 		default:
    265 			DE_FATAL("Unknown image view type");
    266 			break;
    267 	}
    268 
    269 	return samplerType.str();
    270 }
    271 
    272 tcu::UVec2 ImageViewTest::getRenderSize (VkImageViewType viewType)
    273 {
    274 	if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
    275 		return tcu::UVec2(16u, 16u);
    276 	else
    277 		return tcu::UVec2(16u * 3u, 16u * 2u);
    278 }
    279 
    280 tcu::IVec3 ImageViewTest::getImageSize (VkImageViewType viewType)
    281 {
    282 	switch (viewType)
    283 	{
    284 		case VK_IMAGE_VIEW_TYPE_1D:
    285 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
    286 			return tcu::IVec3(16, 1, 1);
    287 
    288 		case VK_IMAGE_VIEW_TYPE_3D:
    289 			return tcu::IVec3(16);
    290 
    291 		default:
    292 			break;
    293 	}
    294 
    295 	return tcu::IVec3(16, 16, 1);
    296 }
    297 
    298 int ImageViewTest::getArraySize (VkImageViewType viewType)
    299 {
    300 	switch (viewType)
    301 	{
    302 		case VK_IMAGE_VIEW_TYPE_3D:
    303 			return 1;
    304 
    305 		case VK_IMAGE_VIEW_TYPE_CUBE:
    306 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
    307 			return 18;
    308 
    309 		default:
    310 			break;
    311 	}
    312 
    313 	return 6;
    314 }
    315 
    316 int ImageViewTest::getNumLevels (VkImageViewType viewType)
    317 {
    318 	const tcu::IVec3 imageSize = getImageSize(viewType);
    319 
    320 	return deLog2Floor32(deMax32(imageSize.x(), deMax32(imageSize.y(), imageSize.z()))) + 1;
    321 }
    322 
    323 static std::string getFormatCaseName (const VkFormat format)
    324 {
    325 	const std::string fullName = getFormatName(format);
    326 
    327 	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
    328 
    329 	return de::toLower(fullName.substr(10));
    330 }
    331 
    332 static de::MovePtr<tcu::TestCaseGroup> createSubresourceRangeTests(tcu::TestContext& testCtx, VkImageViewType viewType, VkFormat imageFormat)
    333 {
    334 	struct TestCaseConfig
    335 	{
    336 		const char*				name;
    337 		float					samplerLod;
    338 		VkImageSubresourceRange	subresourceRange;
    339 	};
    340 
    341 	const deUint32				numLevels				= ImageViewTest::getNumLevels(viewType);
    342 	const deUint32				arraySize				= ImageViewTest::getArraySize(viewType);
    343 	const VkImageAspectFlags	imageAspectFlags		= VK_IMAGE_ASPECT_COLOR_BIT;
    344 	const VkComponentMapping	componentMapping		= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    345 
    346 	de::MovePtr<tcu::TestCaseGroup> rangeTests (new tcu::TestCaseGroup(testCtx, "subresource_range", ""));
    347 
    348 #define ADD_SUBRESOURCE_RANGE_TESTS(TEST_CASES)															\
    349 	do {																								\
    350 		for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(TEST_CASES); configNdx++)				\
    351 		{																								\
    352 			std::ostringstream		desc;																\
    353 			const TestCaseConfig	config	= (TEST_CASES)[configNdx];									\
    354 			desc << "Samples level " << config.samplerLod << " with :\n" << config.subresourceRange;	\
    355 			rangeTests->addChild(new ImageViewTest(testCtx, config.name, desc.str().c_str(), viewType,	\
    356 												   imageFormat, config.samplerLod, componentMapping,	\
    357 												   config.subresourceRange));							\
    358 		}																								\
    359 	} while (deGetFalse())
    360 
    361 	if (viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY)
    362 	{
    363 		const TestCaseConfig mipLevelRangeCases[] =
    364 		{
    365 			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    366 			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
    367 			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, arraySize } },
    368 		};
    369 
    370 		const TestCaseConfig arrayRangeCases[] =
    371 		{
    372 			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    373 			{ "base_array_layer",		0.0f,			{ imageAspectFlags, 0u, numLevels, 1u, arraySize - 1u } },
    374 			{ "array_size",				0.0f,			{ imageAspectFlags, 0u, numLevels, 0u, 4u } },
    375 			{ "array_base_and_size",	0.0f,			{ imageAspectFlags, 0u, numLevels, 2u, 3u } },
    376 		};
    377 
    378 		const TestCaseConfig mipLevelAndArrayRangeCases[] =
    379 		{
    380 			//	name										samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    381 			{ "lod_base_mip_level_base_array_layer",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 1u, 5u } },
    382 			{ "lod_mip_levels_base_array_layer",			4.0f,			{ imageAspectFlags, 0u, 3u, 1u, 5u } },
    383 
    384 			{ "lod_base_mip_level_array_size",				0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 0u, 4u } },
    385 			{ "lod_mip_levels_array_size",					4.0f,			{ imageAspectFlags, 0u, 3u, 0u, 4u } },
    386 
    387 			{ "lod_base_mip_level_array_base_and_size",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 2u, 3u } },
    388 			{ "lod_mip_levels_array_base_and_size",			4.0f,			{ imageAspectFlags, 0u, 3u, 2u, 3u } },
    389 		};
    390 
    391 		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
    392 		{
    393 			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    394 			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,	arraySize					} },
    395 			{ "base_array_layer_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					1u,	VK_REMAINING_ARRAY_LAYERS	} },
    396 			{ "lod_base_mip_level_base_array_layer_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	2u,	VK_REMAINING_ARRAY_LAYERS	} },
    397 		};
    398 
    399 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
    400 		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
    401 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
    402 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
    403 	}
    404 	else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
    405 	{
    406 		const TestCaseConfig mipLevelRangeCases[] =
    407 		{
    408 			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    409 			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
    410 			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, arraySize } },
    411 		};
    412 
    413 		const TestCaseConfig arrayRangeCases[] =
    414 		{
    415 			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    416 			{ "base_array_layer",		0.0f,			{ imageAspectFlags, 0u, numLevels, 6u, arraySize - 6u } },
    417 			{ "array_size",				0.0f,			{ imageAspectFlags, 0u, numLevels, 0u, 6u } },
    418 			{ "array_base_and_size",	0.0f,			{ imageAspectFlags, 0u, numLevels, 12u, 6u } },
    419 		};
    420 
    421 		const TestCaseConfig mipLevelAndArrayRangeCases[] =
    422 		{
    423 			//	name										samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    424 			{ "lod_base_mip_level_base_array_layer",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 6u, arraySize - 6u } },
    425 			{ "lod_mip_levels_base_array_layer",			4.0f,			{ imageAspectFlags, 0u, 3u, 6u, arraySize - 6u } },
    426 
    427 			{ "lod_base_mip_level_array_size",				0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
    428 			{ "lod_mip_levels_array_size",					4.0f,			{ imageAspectFlags, 0u, 3u, 0u, 6u } },
    429 
    430 			{ "lod_base_mip_level_array_base_and_size",		0.0f,			{ imageAspectFlags, 2u, numLevels - 2u, 12u, 6u } },
    431 			{ "lod_mip_levels_array_base_and_size",			4.0f,			{ imageAspectFlags, 0u, 3u, 12u, 6u } },
    432 		};
    433 
    434 		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
    435 		{
    436 			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    437 			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,		arraySize					} },
    438 			{ "base_array_layer_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					6u,		VK_REMAINING_ARRAY_LAYERS	} },
    439 			{ "lod_base_mip_level_base_array_layer_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	12u,	VK_REMAINING_ARRAY_LAYERS	} },
    440 		};
    441 
    442 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
    443 		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
    444 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
    445 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
    446 	}
    447 	else if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
    448 	{
    449 		const TestCaseConfig mipLevelRangeCases[] =
    450 		{
    451 			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    452 			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, 1u } },
    453 			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, 1u } },
    454 		};
    455 
    456 		const TestCaseConfig arrayRangeCases[] =
    457 		{
    458 			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    459 			{ "array_layer_second",		0.0f,			{ imageAspectFlags, 0u, numLevels, 1u, 1u } },
    460 			{ "array_layer_last",		0.0f,			{ imageAspectFlags, 0u, numLevels, arraySize - 1u, 1u } },
    461 		};
    462 
    463 		const TestCaseConfig mipLevelAndArrayRangeCases[] =
    464 		{
    465 			//	name									samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    466 			{ "lod_base_mip_level_array_layer_second",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 1u, 1u } },
    467 			{ "lod_mip_levels_array_layer_second",		4.0f,		{ imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
    468 
    469 			{ "lod_base_mip_level_array_layer_last",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 5u, 1u } },
    470 			{ "lod_mip_levels_array_layer_last",		4.0f,		{ imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } },
    471 		};
    472 
    473 		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
    474 		{
    475 			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    476 			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,				1u							} },
    477 			{ "array_layer_last_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					arraySize - 1u,	VK_REMAINING_ARRAY_LAYERS	} },
    478 			{ "lod_base_mip_level_array_layer_last_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	arraySize - 1u,	VK_REMAINING_ARRAY_LAYERS	} },
    479 		};
    480 
    481 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
    482 		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
    483 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
    484 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
    485 	}
    486 	else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE)
    487 	{
    488 		const TestCaseConfig mipLevelRangeCases[] =
    489 		{
    490 			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    491 			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } },
    492 			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, 6u } },
    493 		};
    494 
    495 		const TestCaseConfig arrayRangeCases[] =
    496 		{
    497 			//	name					samplerLod		subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    498 			{ "array_layer_second",		0.0f,			{ imageAspectFlags, 0u, numLevels, 6u, 6u } },
    499 			{ "array_layer_last",		0.0f,			{ imageAspectFlags, 0u, numLevels, arraySize - 6u, 6u } },
    500 		};
    501 
    502 		const TestCaseConfig mipLevelAndArrayRangeCases[] =
    503 		{
    504 			//	name									samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    505 			{ "lod_base_mip_level_array_layer_second",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 6u, 6u } },
    506 			{ "lod_mip_levels_array_layer_second",		4.0f,		{ imageAspectFlags, 0u, 3u, 6u, 6u } },
    507 
    508 			{ "lod_base_mip_level_array_layer_last",	0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, arraySize - 6u, 6u } },
    509 			{ "lod_mip_levels_array_layer_last",		4.0f,		{ imageAspectFlags, 0u, 3u, arraySize - 6u, 6u } },
    510 		};
    511 
    512 		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
    513 		{
    514 			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    515 			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,				6u							} },
    516 			{ "array_layer_last_remaining_layers",									0.0f,		{ imageAspectFlags,	0u,	numLevels,					arraySize - 6u,	VK_REMAINING_ARRAY_LAYERS	} },
    517 			{ "lod_base_mip_level_array_layer_last_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	arraySize - 6u,	VK_REMAINING_ARRAY_LAYERS	} },
    518 		};
    519 
    520 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
    521 		ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases);
    522 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases);
    523 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
    524 	}
    525 	else if (viewType == VK_IMAGE_VIEW_TYPE_3D)
    526 	{
    527 		const TestCaseConfig mipLevelRangeCases[] =
    528 		{
    529 			//	name					samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    530 			{ "lod_base_mip_level",		0.0f,		{ imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } },
    531 			{ "lod_mip_levels",			4.0f,		{ imageAspectFlags, 0u, 3u, 0u, arraySize } },
    532 		};
    533 
    534 		const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] =
    535 		{
    536 			//	name																samplerLod	subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize)
    537 			{ "lod_base_mip_level_remaining_levels",								0.0f,		{ imageAspectFlags,	1u,	VK_REMAINING_MIP_LEVELS,	0u,	arraySize					} },
    538 			{ "single_array_layer_remaining_layers",								0.0f,		{ imageAspectFlags,	0u,	numLevels,					0u,	VK_REMAINING_ARRAY_LAYERS	} },
    539 			{ "lod_base_mip_level_single_array_layer_remaining_levels_and_layers",	0.0f,		{ imageAspectFlags,	2u,	VK_REMAINING_MIP_LEVELS,	0u,	VK_REMAINING_ARRAY_LAYERS	} },
    540 		};
    541 
    542 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases);
    543 		ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases);
    544 	}
    545 
    546 #undef ADD_SUBRESOURCE_RANGE_TESTS
    547 
    548 	return rangeTests;
    549 }
    550 
    551 static std::vector<VkComponentMapping> getComponentMappingPermutations (const VkComponentMapping& componentMapping)
    552 {
    553 	std::vector<VkComponentMapping> mappings;
    554 
    555 	const VkComponentSwizzle channelSwizzles[4] = { componentMapping.r, componentMapping.g, componentMapping.b, componentMapping.a };
    556 
    557 	// Rearranges the channels by shifting their positions.
    558 	for (int firstChannelNdx = 0; firstChannelNdx < 4; firstChannelNdx++)
    559 	{
    560 		VkComponentSwizzle currentChannel[4];
    561 
    562 		for (int channelNdx = 0; channelNdx < 4; channelNdx++)
    563 			currentChannel[channelNdx] = channelSwizzles[(firstChannelNdx + channelNdx) % 4];
    564 
    565 		const VkComponentMapping mappingPermutation  =
    566 		{
    567 			currentChannel[0],
    568 			currentChannel[1],
    569 			currentChannel[2],
    570 			currentChannel[3]
    571 		};
    572 
    573 		mappings.push_back(mappingPermutation);
    574 	}
    575 
    576 	return mappings;
    577 }
    578 
    579 static std::string getComponentSwizzleCaseName (VkComponentSwizzle componentSwizzle)
    580 {
    581 	const std::string fullName = getComponentSwizzleName(componentSwizzle);
    582 
    583 	DE_ASSERT(de::beginsWith(fullName, "VK_COMPONENT_SWIZZLE_"));
    584 
    585 	return de::toLower(fullName.substr(21));
    586 }
    587 
    588 static std::string getComponentMappingCaseName (const VkComponentMapping& componentMapping)
    589 {
    590 	std::ostringstream name;
    591 
    592 	name << getComponentSwizzleCaseName(componentMapping.r) << "_"
    593 		 << getComponentSwizzleCaseName(componentMapping.g) << "_"
    594 		 << getComponentSwizzleCaseName(componentMapping.b) << "_"
    595 		 << getComponentSwizzleCaseName(componentMapping.a);
    596 
    597 	return name.str();
    598 }
    599 
    600 static de::MovePtr<tcu::TestCaseGroup> createComponentSwizzleTests (tcu::TestContext& testCtx, VkImageViewType viewType, VkFormat imageFormat)
    601 {
    602 	deUint32 arraySize = 0;
    603 
    604 	switch (viewType)
    605 	{
    606 		case VK_IMAGE_VIEW_TYPE_1D:
    607 		case VK_IMAGE_VIEW_TYPE_2D:
    608 		case VK_IMAGE_VIEW_TYPE_3D:
    609 			arraySize = 1;
    610 			break;
    611 
    612 		case VK_IMAGE_VIEW_TYPE_CUBE:
    613 			arraySize = 6;
    614 			break;
    615 
    616 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
    617 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
    618 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
    619 			arraySize = ImageViewTest::getArraySize(viewType);
    620 			break;
    621 
    622 		default:
    623 			break;
    624 	}
    625 
    626 	const VkImageSubresourceRange subresourceRange =
    627 	{
    628 		VK_IMAGE_ASPECT_COLOR_BIT,							// VkImageAspectFlags	aspectMask;
    629 		0u,													// deUint32				baseMipLevel;
    630 		(deUint32)ImageViewTest::getNumLevels(viewType),	// deUint32				mipLevels;
    631 		0u,													// deUint32				baseArrayLayer;
    632 		arraySize,											// deUint32				arraySize;
    633 	};
    634 
    635 	const VkComponentMapping				baseMapping			= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    636 	const std::vector<VkComponentMapping>	componentMappings	= getComponentMappingPermutations(baseMapping);
    637 	de::MovePtr<tcu::TestCaseGroup>			swizzleTests		(new tcu::TestCaseGroup(testCtx, "component_swizzle", ""));
    638 
    639 	for (size_t mappingNdx = 0; mappingNdx < componentMappings.size(); mappingNdx++)
    640 	{
    641 		swizzleTests->addChild(new ImageViewTest(testCtx,
    642 												 getComponentMappingCaseName(componentMappings[mappingNdx]).c_str(),
    643 												 "",
    644 												 viewType,
    645 												 imageFormat,
    646 												 0.0f,
    647 												 componentMappings[mappingNdx],
    648 												 subresourceRange));
    649 	}
    650 
    651 	return swizzleTests;
    652 }
    653 
    654 } // anonymous
    655 
    656 tcu::TestCaseGroup* createImageViewTests (tcu::TestContext& testCtx)
    657 {
    658 	const struct
    659 	{
    660 		VkImageViewType		type;
    661 		const char*			name;
    662 	}
    663 	imageViewTypes[] =
    664 	{
    665 		{ VK_IMAGE_VIEW_TYPE_1D,			"1d" },
    666 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array" },
    667 		{ VK_IMAGE_VIEW_TYPE_2D,			"2d" },
    668 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array" },
    669 		{ VK_IMAGE_VIEW_TYPE_3D,			"3d" },
    670 		{ VK_IMAGE_VIEW_TYPE_CUBE,			"cube" },
    671 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array" }
    672 	};
    673 
    674 	const VkFormat formats[] =
    675 	{
    676 		VK_FORMAT_R4G4_UNORM_PACK8,
    677 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
    678 		VK_FORMAT_R5G6B5_UNORM_PACK16,
    679 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
    680 		VK_FORMAT_R8_UNORM,
    681 		VK_FORMAT_R8_SNORM,
    682 		VK_FORMAT_R8_USCALED,
    683 		VK_FORMAT_R8_SSCALED,
    684 		VK_FORMAT_R8_UINT,
    685 		VK_FORMAT_R8_SINT,
    686 		VK_FORMAT_R8_SRGB,
    687 		VK_FORMAT_R8G8_UNORM,
    688 		VK_FORMAT_R8G8_SNORM,
    689 		VK_FORMAT_R8G8_USCALED,
    690 		VK_FORMAT_R8G8_SSCALED,
    691 		VK_FORMAT_R8G8_UINT,
    692 		VK_FORMAT_R8G8_SINT,
    693 		VK_FORMAT_R8G8_SRGB,
    694 		VK_FORMAT_R8G8B8_UNORM,
    695 		VK_FORMAT_R8G8B8_SNORM,
    696 		VK_FORMAT_R8G8B8_USCALED,
    697 		VK_FORMAT_R8G8B8_SSCALED,
    698 		VK_FORMAT_R8G8B8_UINT,
    699 		VK_FORMAT_R8G8B8_SINT,
    700 		VK_FORMAT_R8G8B8_SRGB,
    701 		VK_FORMAT_R8G8B8A8_UNORM,
    702 		VK_FORMAT_R8G8B8A8_SNORM,
    703 		VK_FORMAT_R8G8B8A8_USCALED,
    704 		VK_FORMAT_R8G8B8A8_SSCALED,
    705 		VK_FORMAT_R8G8B8A8_UINT,
    706 		VK_FORMAT_R8G8B8A8_SINT,
    707 		VK_FORMAT_R8G8B8A8_SRGB,
    708 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
    709 		VK_FORMAT_A2R10G10B10_UINT_PACK32,
    710 		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
    711 		VK_FORMAT_R16_UNORM,
    712 		VK_FORMAT_R16_SNORM,
    713 		VK_FORMAT_R16_USCALED,
    714 		VK_FORMAT_R16_SSCALED,
    715 		VK_FORMAT_R16_UINT,
    716 		VK_FORMAT_R16_SINT,
    717 		VK_FORMAT_R16_SFLOAT,
    718 		VK_FORMAT_R16G16_UNORM,
    719 		VK_FORMAT_R16G16_SNORM,
    720 		VK_FORMAT_R16G16_USCALED,
    721 		VK_FORMAT_R16G16_SSCALED,
    722 		VK_FORMAT_R16G16_UINT,
    723 		VK_FORMAT_R16G16_SINT,
    724 		VK_FORMAT_R16G16_SFLOAT,
    725 		VK_FORMAT_R16G16B16_UNORM,
    726 		VK_FORMAT_R16G16B16_SNORM,
    727 		VK_FORMAT_R16G16B16_USCALED,
    728 		VK_FORMAT_R16G16B16_SSCALED,
    729 		VK_FORMAT_R16G16B16_UINT,
    730 		VK_FORMAT_R16G16B16_SINT,
    731 		VK_FORMAT_R16G16B16_SFLOAT,
    732 		VK_FORMAT_R16G16B16A16_UNORM,
    733 		VK_FORMAT_R16G16B16A16_SNORM,
    734 		VK_FORMAT_R16G16B16A16_USCALED,
    735 		VK_FORMAT_R16G16B16A16_SSCALED,
    736 		VK_FORMAT_R16G16B16A16_UINT,
    737 		VK_FORMAT_R16G16B16A16_SINT,
    738 		VK_FORMAT_R16G16B16A16_SFLOAT,
    739 		VK_FORMAT_R32_UINT,
    740 		VK_FORMAT_R32_SINT,
    741 		VK_FORMAT_R32_SFLOAT,
    742 		VK_FORMAT_R32G32_UINT,
    743 		VK_FORMAT_R32G32_SINT,
    744 		VK_FORMAT_R32G32_SFLOAT,
    745 		VK_FORMAT_R32G32B32_UINT,
    746 		VK_FORMAT_R32G32B32_SINT,
    747 		VK_FORMAT_R32G32B32_SFLOAT,
    748 		VK_FORMAT_R32G32B32A32_UINT,
    749 		VK_FORMAT_R32G32B32A32_SINT,
    750 		VK_FORMAT_R32G32B32A32_SFLOAT,
    751 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
    752 		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
    753 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
    754 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
    755 
    756 		// Compressed formats
    757 		VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
    758 		VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
    759 		VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
    760 		VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
    761 		VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
    762 		VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
    763 		VK_FORMAT_EAC_R11_UNORM_BLOCK,
    764 		VK_FORMAT_EAC_R11_SNORM_BLOCK,
    765 		VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
    766 		VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
    767 		VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
    768 		VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
    769 		VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
    770 		VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
    771 		VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
    772 		VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
    773 		VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
    774 		VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
    775 		VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
    776 		VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
    777 		VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
    778 		VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
    779 		VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
    780 		VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
    781 		VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
    782 		VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
    783 		VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
    784 		VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
    785 		VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
    786 		VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
    787 		VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
    788 		VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
    789 		VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
    790 		VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
    791 		VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
    792 		VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
    793 		VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
    794 		VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
    795 	};
    796 
    797 	de::MovePtr<tcu::TestCaseGroup> imageTests			(new tcu::TestCaseGroup(testCtx, "image_view", "Image tests"));
    798 	de::MovePtr<tcu::TestCaseGroup> viewTypeTests		(new tcu::TestCaseGroup(testCtx, "view_type", ""));
    799 
    800 	for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
    801 	{
    802 		const VkImageViewType			viewType		= imageViewTypes[viewTypeNdx].type;
    803 		de::MovePtr<tcu::TestCaseGroup>	viewTypeGroup	(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
    804 		de::MovePtr<tcu::TestCaseGroup>	formatTests		(new tcu::TestCaseGroup(testCtx, "format", "Uses samplable formats"));
    805 
    806 		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
    807 		{
    808 			const VkFormat		format		= formats[formatNdx];
    809 
    810 			if (isCompressedFormat(format))
    811 			{
    812 				// Do not use compressed formats with 1D and 1D array textures.
    813 				if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
    814 					break;
    815 			}
    816 
    817 			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx,
    818 																				getFormatCaseName(format).c_str(),
    819 																				(std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
    820 
    821 			de::MovePtr<tcu::TestCaseGroup>	subresourceRangeTests	= createSubresourceRangeTests(testCtx, viewType, format);
    822 			de::MovePtr<tcu::TestCaseGroup>	componentSwizzleTests	= createComponentSwizzleTests(testCtx, viewType, format);
    823 
    824 			formatGroup->addChild(componentSwizzleTests.release());
    825 			formatGroup->addChild(subresourceRangeTests.release());
    826 			formatTests->addChild(formatGroup.release());
    827 		}
    828 
    829 		viewTypeGroup->addChild(formatTests.release());
    830 		viewTypeTests->addChild(viewTypeGroup.release());
    831 	}
    832 
    833 	imageTests->addChild(viewTypeTests.release());
    834 
    835 	return imageTests.release();
    836 }
    837 
    838 } // pipeline
    839 } // vkt
    840