1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 * Copyright (c) 2023 LunarG, Inc.
8 * Copyright (c) 2023 Nintendo
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 *      http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 *//*!
23 * \file
24 * \brief Image Tests
25 *//*--------------------------------------------------------------------*/
26
27#include "vktPipelineImageTests.hpp"
28#include "vktPipelineImageSamplingInstance.hpp"
29#include "vktPipelineImageUtil.hpp"
30#include "vktPipelineVertexUtil.hpp"
31#include "vktTestCase.hpp"
32#include "vkImageUtil.hpp"
33#include "vkPrograms.hpp"
34#include "tcuTextureUtil.hpp"
35#include "deStringUtil.hpp"
36
37#include <sstream>
38#include <vector>
39
40namespace vkt
41{
42namespace pipeline
43{
44
45using namespace vk;
46using de::MovePtr;
47
48namespace
49{
50
51class ImageTest : public vkt::TestCase
52{
53public:
54							ImageTest							(tcu::TestContext&	testContext,
55																 const char*				name,
56																 AllocationKind				allocationKind,
57																 PipelineConstructionType	pipelineConstructionType,
58																 VkDescriptorType			samplingType,
59																 VkImageViewType			imageViewType,
60																 VkFormat					imageFormat,
61																 const tcu::IVec3&			imageSize,
62																 int						imageCount,
63																 int						arraySize,
64																 bool						pipelineProtectedAccess,
65																 bool						pipelineProtectedFlag);
66
67	ImageSamplingInstanceParams	getImageSamplingInstanceParams	(AllocationKind		allocationKind,
68																 VkDescriptorType	samplingType,
69																 VkImageViewType	imageViewType,
70																 VkFormat			imageFormat,
71																 const tcu::IVec3&	imageSize,
72																 int				imageCount,
73																 int				arraySize) const;
74
75	virtual void			initPrograms						(SourceCollections& sourceCollections) const;
76	virtual void			checkSupport						(Context& context) const;
77	virtual TestInstance*	createInstance						(Context& context) const;
78	static std::string		getGlslSamplerType					(const tcu::TextureFormat& format, VkImageViewType type);
79	static std::string		getGlslTextureType					(const tcu::TextureFormat& format, VkImageViewType type);
80	static std::string		getGlslSamplerDecl					(int imageCount);
81	static std::string		getGlslTextureDecl					(int imageCount);
82	static std::string		getGlslFragColorDecl				(int imageCount);
83	static std::string		getGlslSampler						(const tcu::TextureFormat&	format,
84																 VkImageViewType			type,
85																 VkDescriptorType			samplingType,
86																 int						imageCount);
87
88private:
89	AllocationKind				m_allocationKind;
90	PipelineConstructionType	m_pipelineConstructionType;
91	VkDescriptorType			m_samplingType;
92	VkImageViewType				m_imageViewType;
93	VkFormat					m_imageFormat;
94	tcu::IVec3					m_imageSize;
95	int							m_imageCount;
96	int							m_arraySize;
97	bool						m_pipelineProtectedAccess;
98	bool						m_pipelineProtectedFlag;
99};
100
101ImageTest::ImageTest (tcu::TestContext&	testContext,
102					  const char*				name,
103					  AllocationKind			allocationKind,
104					  PipelineConstructionType	pipelineConstructionType,
105					  VkDescriptorType			samplingType,
106					  VkImageViewType			imageViewType,
107					  VkFormat					imageFormat,
108					  const tcu::IVec3&			imageSize,
109					  int						imageCount,
110					  int						arraySize,
111					  bool						pipelineProtectedAccess,
112					  bool						pipelineProtectedFlag)
113
114	: vkt::TestCase					(testContext, name)
115	, m_allocationKind				(allocationKind)
116	, m_pipelineConstructionType	(pipelineConstructionType)
117	, m_samplingType				(samplingType)
118	, m_imageViewType				(imageViewType)
119	, m_imageFormat					(imageFormat)
120	, m_imageSize					(imageSize)
121	, m_imageCount					(imageCount)
122	, m_arraySize					(arraySize)
123	, m_pipelineProtectedAccess		(pipelineProtectedAccess)
124	, m_pipelineProtectedFlag		(pipelineProtectedFlag)
125{
126}
127
128void ImageTest::checkSupport (Context& context) const
129{
130	// Using a loop to index into an array of images requires shaderSampledImageArrayDynamicIndexing
131	if (m_imageCount > 1)
132		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING);
133
134#ifndef CTS_USES_VULKANSC
135	if (m_imageFormat == VK_FORMAT_A8_UNORM_KHR || m_imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
136		context.requireDeviceFunctionality("VK_KHR_maintenance5");
137#endif // CTS_USES_VULKANSC
138
139	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
140	checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_allocationKind, m_samplingType, m_imageViewType, m_imageFormat, m_imageSize, m_imageCount, m_arraySize));
141
142	if (m_pipelineProtectedAccess)
143	{
144#ifndef CTS_USES_VULKANSC
145		context.requireDeviceFunctionality("VK_EXT_pipeline_protected_access");
146
147		if (!context.getPipelineProtectedAccessFeaturesEXT().pipelineProtectedAccess)
148		{
149			throw tcu::NotSupportedError("pipelineProtectedAccess feature is not supported");
150		}
151#else // CTS_USES_VULKANSC
152		throw tcu::NotSupportedError("pipeline protected access is not supported");
153#endif // CTS_USES_VULKANSC
154	}
155}
156
157ImageSamplingInstanceParams ImageTest::getImageSamplingInstanceParams (AllocationKind		allocationKind,
158																	   VkDescriptorType		samplingType,
159																	   VkImageViewType		imageViewType,
160																	   VkFormat				imageFormat,
161																	   const tcu::IVec3&	imageSize,
162																	   int					imageCount,
163																	   int					arraySize) const
164{
165	tcu::UVec2 renderSize;
166
167	if (imageViewType == VK_IMAGE_VIEW_TYPE_1D || imageViewType == VK_IMAGE_VIEW_TYPE_2D)
168	{
169		renderSize = tcu::UVec2((deUint32)imageSize.x(), (deUint32)imageSize.y());
170	}
171	else
172	{
173		// Draw a 3x2 grid of texture layers
174		renderSize = tcu::UVec2((deUint32)imageSize.x() * 3, (deUint32)imageSize.y() * 2);
175	}
176
177	const bool						separateStencilUsage	= false;
178	const std::vector<Vertex4Tex4>	vertices				= createTestQuadMosaic(imageViewType);
179	const VkComponentMapping		componentMapping		= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
180	const VkImageSubresourceRange	subresourceRange		=
181	{
182		VK_IMAGE_ASPECT_COLOR_BIT,
183		0u,
184		(deUint32)deLog2Floor32(deMax32(imageSize.x(), deMax32(imageSize.y(), imageSize.z()))) + 1,
185		0u,
186		(deUint32)arraySize,
187	};
188
189	const VkSamplerCreateInfo samplerParams =
190	{
191		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,										// VkStructureType			sType;
192		DE_NULL,																	// const void*				pNext;
193		0u,																			// VkSamplerCreateFlags		flags;
194		VK_FILTER_NEAREST,															// VkFilter					magFilter;
195		VK_FILTER_NEAREST,															// VkFilter					minFilter;
196		VK_SAMPLER_MIPMAP_MODE_NEAREST,												// VkSamplerMipmapMode		mipmapMode;
197		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,										// VkSamplerAddressMode		addressModeU;
198		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,										// VkSamplerAddressMode		addressModeV;
199		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,										// VkSamplerAddressMode		addressModeW;
200		0.0f,																		// float					mipLodBias;
201		VK_FALSE,																	// VkBool32					anisotropyEnable;
202		1.0f,																		// float					maxAnisotropy;
203		false,																		// VkBool32					compareEnable;
204		VK_COMPARE_OP_NEVER,														// VkCompareOp				compareOp;
205		0.0f,																		// float					minLod;
206		(float)(subresourceRange.levelCount - 1),									// float					maxLod;
207		getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, imageFormat, false),	// VkBorderColor			borderColor;
208		false																		// VkBool32					unnormalizedCoordinates;
209	};
210
211#ifdef CTS_USES_VULKANSC
212	const vk::VkPipelineCreateFlags pipelineFlags = (vk::VkPipelineCreateFlagBits)0u;
213	(void)m_pipelineProtectedFlag;
214#else // CTS_USES_VULKANSC
215	const vk::VkPipelineCreateFlags pipelineFlags = m_pipelineProtectedFlag ? vk::VK_PIPELINE_CREATE_NO_PROTECTED_ACCESS_BIT_EXT : (vk::VkPipelineCreateFlagBits)0u;
216#endif // CTS_USES_VULKANSC
217
218	return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat, imageSize, arraySize, componentMapping, subresourceRange, samplerParams, 0.0f, vertices, separateStencilUsage, samplingType, imageCount, allocationKind, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, pipelineFlags);
219}
220
221void ImageTest::initPrograms (SourceCollections& sourceCollections) const
222{
223	std::ostringstream				vertexSrc;
224	std::ostringstream				fragmentSrc;
225	const char*						texCoordSwizzle	= DE_NULL;
226	const tcu::TextureFormat		format			= (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
227																						  : mapVkFormat(m_imageFormat);
228
229	tcu::Vec4						lookupScale;
230	tcu::Vec4						lookupBias;
231
232	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
233
234	switch (m_imageViewType)
235	{
236		case VK_IMAGE_VIEW_TYPE_1D:
237			texCoordSwizzle = "x";
238			break;
239		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
240		case VK_IMAGE_VIEW_TYPE_2D:
241			texCoordSwizzle = "xy";
242			break;
243		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
244		case VK_IMAGE_VIEW_TYPE_3D:
245		case VK_IMAGE_VIEW_TYPE_CUBE:
246			texCoordSwizzle = "xyz";
247			break;
248		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
249			texCoordSwizzle = "xyzw";
250			break;
251		default:
252			DE_ASSERT(false);
253			break;
254	}
255
256	vertexSrc << "#version 440\n"
257			  << "layout(location = 0) in vec4 position;\n"
258			  << "layout(location = 1) in vec4 texCoords;\n"
259			  << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
260			  << "out gl_PerVertex {\n"
261			  << "	vec4 gl_Position;\n"
262			  << "};\n"
263			  << "void main (void)\n"
264			  << "{\n"
265			  << "	gl_Position = position;\n"
266			  << "	vtxTexCoords = texCoords;\n"
267			  << "}\n";
268
269	fragmentSrc << "#version 440\n";
270	switch (m_samplingType)
271	{
272		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
273			fragmentSrc
274				<< "layout(set = 0, binding = 0) uniform highp sampler texSampler;\n"
275				<< "layout(set = 0, binding = 1) uniform highp " << getGlslTextureType(format, m_imageViewType) << " " << getGlslTextureDecl(m_imageCount) << ";\n";
276			break;
277		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
278		default:
279			fragmentSrc
280				<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " " << getGlslSamplerDecl(m_imageCount) << ";\n";
281	}
282	fragmentSrc << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
283				<< "layout(location = 0) out highp vec4 " << getGlslFragColorDecl(m_imageCount) << ";\n"
284				<< "void main (void)\n"
285				<< "{\n";
286	if (m_imageCount > 1)
287		fragmentSrc
288				<< "	for (uint i = 0; i < " << m_imageCount << "; ++i)\n"
289				<< "		fragColors[i] = (texture(" << getGlslSampler(format, m_imageViewType, m_samplingType, m_imageCount) << ", vtxTexCoords." << texCoordSwizzle << std::scientific << ") * vec4" << lookupScale << ") + vec4" << lookupBias << "; \n";
290	else
291		fragmentSrc
292				<< "	fragColor = (texture(" << getGlslSampler(format, m_imageViewType, m_samplingType, m_imageCount) << ", vtxTexCoords." << texCoordSwizzle << std::scientific << ") * vec4" << lookupScale << ") + vec4" << lookupBias << "; \n";
293	fragmentSrc << "}\n";
294
295	sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
296	sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
297}
298
299TestInstance* ImageTest::createInstance (Context& context) const
300{
301	return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_allocationKind, m_samplingType, m_imageViewType, m_imageFormat, m_imageSize, m_imageCount, m_arraySize));
302}
303
304std::string ImageTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
305{
306	std::ostringstream samplerType;
307
308	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
309		samplerType << "u";
310	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
311		samplerType << "i";
312
313	switch (type)
314	{
315		case VK_IMAGE_VIEW_TYPE_1D:
316			samplerType << "sampler1D";
317			break;
318
319		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
320			samplerType << "sampler1DArray";
321			break;
322
323		case VK_IMAGE_VIEW_TYPE_2D:
324			samplerType << "sampler2D";
325			break;
326
327		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
328			samplerType << "sampler2DArray";
329			break;
330
331		case VK_IMAGE_VIEW_TYPE_3D:
332			samplerType << "sampler3D";
333			break;
334
335		case VK_IMAGE_VIEW_TYPE_CUBE:
336			samplerType << "samplerCube";
337			break;
338
339		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
340			samplerType << "samplerCubeArray";
341			break;
342
343		default:
344			DE_FATAL("Unknown image view type");
345			break;
346	}
347
348	return samplerType.str();
349}
350
351std::string ImageTest::getGlslTextureType (const tcu::TextureFormat& format, VkImageViewType type)
352{
353	std::ostringstream textureType;
354
355	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
356		textureType << "u";
357	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
358		textureType << "i";
359
360	switch (type)
361	{
362		case VK_IMAGE_VIEW_TYPE_1D:
363			textureType << "texture1D";
364			break;
365
366		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
367			textureType << "texture1DArray";
368			break;
369
370		case VK_IMAGE_VIEW_TYPE_2D:
371			textureType << "texture2D";
372			break;
373
374		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
375			textureType << "texture2DArray";
376			break;
377
378		case VK_IMAGE_VIEW_TYPE_3D:
379			textureType << "texture3D";
380			break;
381
382		case VK_IMAGE_VIEW_TYPE_CUBE:
383			textureType << "textureCube";
384			break;
385
386		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
387			textureType << "textureCubeArray";
388			break;
389
390		default:
391			DE_FATAL("Unknown image view type");
392	}
393
394	return textureType.str();
395}
396
397std::string ImageTest::getGlslSamplerDecl (int imageCount)
398{
399	std::ostringstream samplerArray;
400	samplerArray << "texSamplers[" << imageCount << "]";
401
402	return imageCount > 1 ? samplerArray.str() : "texSampler";
403}
404
405std::string ImageTest::getGlslTextureDecl (int imageCount)
406{
407	std::ostringstream textureArray;
408	textureArray << "texImages[" << imageCount << "]";
409
410	return imageCount > 1 ? textureArray.str() : "texImage";
411}
412
413std::string ImageTest::getGlslFragColorDecl (int imageCount)
414{
415	std::ostringstream samplerArray;
416	samplerArray << "fragColors[" << imageCount << "]";
417
418	return imageCount > 1 ? samplerArray.str() : "fragColor";
419}
420
421std::string ImageTest::getGlslSampler (const tcu::TextureFormat& format, VkImageViewType type, VkDescriptorType samplingType, int imageCount)
422{
423	std::string texSampler	= imageCount > 1 ? "texSamplers[i]" : "texSampler";
424	std::string texImage	= imageCount > 1 ? "texImages[i]" : "texImage";
425
426	switch (samplingType)
427	{
428		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
429			return getGlslSamplerType(format, type) + "(" + texImage + ", texSampler)";
430		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
431		default:
432			return texSampler;
433	}
434}
435
436std::string getFormatCaseName (const VkFormat format)
437{
438	const std::string	fullName	= getFormatName(format);
439
440	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
441
442	return de::toLower(fullName.substr(10));
443}
444
445std::string getSizeName (VkImageViewType viewType, const tcu::IVec3& size, int arraySize, bool pipelineProtectedAccess, bool pipelineProtectedFlag)
446{
447	std::ostringstream	caseName;
448
449	if (pipelineProtectedAccess) {
450		caseName << "pipeline_protected_access_";
451	}
452	if (pipelineProtectedFlag) {
453		caseName << "pipeline_protected_flag_";
454	}
455
456	switch (viewType)
457	{
458		case VK_IMAGE_VIEW_TYPE_1D:
459		case VK_IMAGE_VIEW_TYPE_2D:
460		case VK_IMAGE_VIEW_TYPE_CUBE:
461			caseName << size.x() << "x" << size.y();
462			break;
463
464		case VK_IMAGE_VIEW_TYPE_3D:
465			caseName << size.x() << "x" << size.y() << "x" << size.z();
466			break;
467
468		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
469		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
470		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
471			caseName << size.x() << "x" << size.y() << "_array_of_" << arraySize;
472			break;
473
474		default:
475			DE_ASSERT(false);
476			break;
477	}
478
479	return caseName.str();
480}
481
482de::MovePtr<tcu::TestCaseGroup> createImageSizeTests (tcu::TestContext& testCtx, AllocationKind allocationKind, PipelineConstructionType pipelineConstructionType, VkDescriptorType samplingType, VkImageViewType imageViewType, VkFormat imageFormat, int imageCount)
483{
484	using tcu::IVec3;
485
486	std::vector<IVec3>					imageSizes;
487	std::vector<int>					arraySizes;
488	de::MovePtr<tcu::TestCaseGroup>		imageSizeTests	(new tcu::TestCaseGroup(testCtx, "size"));
489
490	const bool pipelineProtectedAccess[] = {
491		false,
492#ifndef CTS_USES_VULKANSC
493		true,
494#endif
495	};
496	const bool pipelineProtectedFlag[] = {
497		false,
498#ifndef CTS_USES_VULKANSC
499		true,
500#endif
501	};
502
503	// Select image imageSizes
504	switch (imageViewType)
505	{
506		case VK_IMAGE_VIEW_TYPE_1D:
507		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
508			// POT
509			if (imageCount == 1)
510			{
511				imageSizes.push_back(IVec3(1, 1, 1));
512				imageSizes.push_back(IVec3(2, 1, 1));
513				imageSizes.push_back(IVec3(32, 1, 1));
514				imageSizes.push_back(IVec3(128, 1, 1));
515			}
516			imageSizes.push_back(IVec3(512, 1, 1));
517
518			// NPOT
519			if (imageCount == 1)
520			{
521				imageSizes.push_back(IVec3(3, 1, 1));
522				imageSizes.push_back(IVec3(13, 1, 1));
523				imageSizes.push_back(IVec3(127, 1, 1));
524			}
525			imageSizes.push_back(IVec3(443, 1, 1));
526			break;
527
528		case VK_IMAGE_VIEW_TYPE_2D:
529		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
530			if (imageCount == 1)
531			{
532				// POT
533				imageSizes.push_back(IVec3(1, 1, 1));
534				imageSizes.push_back(IVec3(2, 2, 1));
535				imageSizes.push_back(IVec3(32, 32, 1));
536
537				// NPOT
538				imageSizes.push_back(IVec3(3, 3, 1));
539				imageSizes.push_back(IVec3(13, 13, 1));
540			}
541
542			// POT rectangular
543			if (imageCount == 1)
544				imageSizes.push_back(IVec3(8, 16, 1));
545			imageSizes.push_back(IVec3(32, 16, 1));
546
547			// NPOT rectangular
548			imageSizes.push_back(IVec3(13, 23, 1));
549			if (imageCount == 1)
550				imageSizes.push_back(IVec3(23, 8, 1));
551			break;
552
553		case VK_IMAGE_VIEW_TYPE_3D:
554			// POT cube
555			if (imageCount == 1)
556			{
557				imageSizes.push_back(IVec3(1, 1, 1));
558				imageSizes.push_back(IVec3(2, 2, 2));
559			}
560			imageSizes.push_back(IVec3(16, 16, 16));
561
562			// NPOT cube
563			if (imageCount == 1)
564			{
565				imageSizes.push_back(IVec3(3, 3, 3));
566				imageSizes.push_back(IVec3(5, 5, 5));
567			}
568			imageSizes.push_back(IVec3(11, 11, 11));
569
570			// POT non-cube
571			if (imageCount == 1)
572				imageSizes.push_back(IVec3(32, 16, 8));
573			imageSizes.push_back(IVec3(8, 16, 32));
574
575			// NPOT non-cube
576			imageSizes.push_back(IVec3(17, 11, 5));
577			if (imageCount == 1)
578				imageSizes.push_back(IVec3(5, 11, 17));
579			break;
580
581		case VK_IMAGE_VIEW_TYPE_CUBE:
582		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
583			// POT
584			imageSizes.push_back(IVec3(32, 32, 1));
585
586			// NPOT
587			imageSizes.push_back(IVec3(13, 13, 1));
588			break;
589
590		default:
591			DE_ASSERT(false);
592			break;
593	}
594
595	// Select array sizes
596	switch (imageViewType)
597	{
598		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
599		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
600			if (imageCount == 1)
601				arraySizes.push_back(3);
602			arraySizes.push_back(6);
603			break;
604
605		case VK_IMAGE_VIEW_TYPE_CUBE:
606			arraySizes.push_back(6);
607			break;
608
609		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
610			if (imageCount == 1)
611				arraySizes.push_back(6);
612			arraySizes.push_back(6 * 6);
613			break;
614
615		default:
616			arraySizes.push_back(1);
617			break;
618	}
619
620	for (size_t protectedNdx = 0; protectedNdx < DE_LENGTH_OF_ARRAY(pipelineProtectedAccess); ++protectedNdx) {
621		for (size_t flagNdx = 0; flagNdx < DE_LENGTH_OF_ARRAY(pipelineProtectedAccess); ++flagNdx) {
622			if (!pipelineProtectedAccess[protectedNdx] && pipelineProtectedFlag[flagNdx]) continue;
623
624			for (size_t sizeNdx = 0; sizeNdx < imageSizes.size(); sizeNdx++)
625			{
626				for (size_t arraySizeNdx = 0; arraySizeNdx < arraySizes.size(); arraySizeNdx++)
627				{
628					imageSizeTests->addChild(new ImageTest(testCtx,
629														   getSizeName(imageViewType, imageSizes[sizeNdx], arraySizes[arraySizeNdx], pipelineProtectedAccess[protectedNdx], pipelineProtectedFlag[flagNdx]).c_str(),
630														   allocationKind,
631														   pipelineConstructionType,
632														   samplingType,
633														   imageViewType,
634														   imageFormat,
635														   imageSizes[sizeNdx],
636														   imageCount,
637														   arraySizes[arraySizeNdx],
638														   pipelineProtectedAccess[protectedNdx],
639														   pipelineProtectedFlag[flagNdx]));
640				}
641			}
642		}
643	}
644
645	return imageSizeTests;
646}
647
648void createImageCountTests (tcu::TestCaseGroup* parentGroup, tcu::TestContext& testCtx, AllocationKind allocationKind, PipelineConstructionType pipelineConstructionType, VkDescriptorType samplingType, VkImageViewType imageViewType, VkFormat imageFormat)
649{
650	const int		coreImageCounts[]					= { 1, 4, 8 };
651	const int		dedicatedAllocationImageCounts[]	= { 1 };
652	const int*		imageCounts							= (allocationKind == ALLOCATION_KIND_DEDICATED)
653														  ? dedicatedAllocationImageCounts
654														  : coreImageCounts;
655	const size_t	imageCountsLength					= (allocationKind == ALLOCATION_KIND_DEDICATED)
656														  ? DE_LENGTH_OF_ARRAY(dedicatedAllocationImageCounts)
657														  : DE_LENGTH_OF_ARRAY(coreImageCounts);
658
659	for (size_t countNdx = 0; countNdx < imageCountsLength; countNdx++)
660	{
661		std::ostringstream	caseName;
662		caseName << "count_" << imageCounts[countNdx];
663		de::MovePtr<tcu::TestCaseGroup>	countGroup(new tcu::TestCaseGroup(testCtx, caseName.str().c_str()));
664		de::MovePtr<tcu::TestCaseGroup> sizeTests = createImageSizeTests(testCtx, allocationKind, pipelineConstructionType, samplingType, imageViewType, imageFormat, imageCounts[countNdx]);
665
666		countGroup->addChild(sizeTests.release());
667		parentGroup->addChild(countGroup.release());
668	}
669}
670
671de::MovePtr<tcu::TestCaseGroup> createImageFormatTests (tcu::TestContext& testCtx, AllocationKind allocationKind, PipelineConstructionType pipelineConstructionType, VkDescriptorType samplingType, VkImageViewType imageViewType)
672{
673	// All supported dEQP formats that are not intended for depth or stencil.
674	const VkFormat coreFormats[]					=
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_A2R10G10B10_USCALED_PACK32,
711		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
712		VK_FORMAT_A2B10G10R10_UINT_PACK32,
713		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
714#ifndef CTS_USES_VULKANSC
715		VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
716#endif // CTS_USES_VULKANSC
717		VK_FORMAT_R16_UNORM,
718		VK_FORMAT_R16_SNORM,
719		VK_FORMAT_R16_USCALED,
720		VK_FORMAT_R16_SSCALED,
721		VK_FORMAT_R16_UINT,
722		VK_FORMAT_R16_SINT,
723		VK_FORMAT_R16_SFLOAT,
724		VK_FORMAT_R16G16_UNORM,
725		VK_FORMAT_R16G16_SNORM,
726		VK_FORMAT_R16G16_USCALED,
727		VK_FORMAT_R16G16_SSCALED,
728		VK_FORMAT_R16G16_UINT,
729		VK_FORMAT_R16G16_SINT,
730		VK_FORMAT_R16G16_SFLOAT,
731		VK_FORMAT_R16G16B16_UNORM,
732		VK_FORMAT_R16G16B16_SNORM,
733		VK_FORMAT_R16G16B16_USCALED,
734		VK_FORMAT_R16G16B16_SSCALED,
735		VK_FORMAT_R16G16B16_UINT,
736		VK_FORMAT_R16G16B16_SINT,
737		VK_FORMAT_R16G16B16_SFLOAT,
738		VK_FORMAT_R16G16B16A16_UNORM,
739		VK_FORMAT_R16G16B16A16_SNORM,
740		VK_FORMAT_R16G16B16A16_USCALED,
741		VK_FORMAT_R16G16B16A16_SSCALED,
742		VK_FORMAT_R16G16B16A16_UINT,
743		VK_FORMAT_R16G16B16A16_SINT,
744		VK_FORMAT_R16G16B16A16_SFLOAT,
745		VK_FORMAT_R32_UINT,
746		VK_FORMAT_R32_SINT,
747		VK_FORMAT_R32_SFLOAT,
748		VK_FORMAT_R32G32_UINT,
749		VK_FORMAT_R32G32_SINT,
750		VK_FORMAT_R32G32_SFLOAT,
751		VK_FORMAT_R32G32B32_UINT,
752		VK_FORMAT_R32G32B32_SINT,
753		VK_FORMAT_R32G32B32_SFLOAT,
754		VK_FORMAT_R32G32B32A32_UINT,
755		VK_FORMAT_R32G32B32A32_SINT,
756		VK_FORMAT_R32G32B32A32_SFLOAT,
757		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
758		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
759		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
760		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
761		VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
762		VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
763#ifndef CTS_USES_VULKANSC
764		VK_FORMAT_A8_UNORM_KHR,
765#endif // CTS_USES_VULKANSC
766
767		// Compressed formats
768		VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
769		VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
770		VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
771		VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
772		VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
773		VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
774		VK_FORMAT_EAC_R11_UNORM_BLOCK,
775		VK_FORMAT_EAC_R11_SNORM_BLOCK,
776		VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
777		VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
778		VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
779		VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
780		VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
781		VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
782		VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
783		VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
784		VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
785		VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
786		VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
787		VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
788		VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
789		VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
790		VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
791		VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
792		VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
793		VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
794		VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
795		VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
796		VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
797		VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
798		VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
799		VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
800		VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
801		VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
802		VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
803		VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
804		VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
805		VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
806	};
807	// Formats to test with dedicated allocation
808	const VkFormat	dedicatedAllocationFormats[]	=
809	{
810		VK_FORMAT_R8G8B8A8_UNORM,
811		VK_FORMAT_R16_SFLOAT,
812	};
813	const VkFormat*	formats							= (allocationKind == ALLOCATION_KIND_DEDICATED)
814													  ? dedicatedAllocationFormats
815													  : coreFormats;
816	const size_t	formatsLength					= (allocationKind == ALLOCATION_KIND_DEDICATED)
817													  ? DE_LENGTH_OF_ARRAY(dedicatedAllocationFormats)
818													  : DE_LENGTH_OF_ARRAY(coreFormats);
819
820	de::MovePtr<tcu::TestCaseGroup>	imageFormatTests(new tcu::TestCaseGroup(testCtx, "format"));
821
822	for (size_t formatNdx = 0; formatNdx < formatsLength; formatNdx++)
823	{
824		const VkFormat	format = formats[formatNdx];
825
826		if (isCompressedFormat(format))
827		{
828			// Do not use compressed formats with 1D and 1D array textures.
829			if (imageViewType == VK_IMAGE_VIEW_TYPE_1D || imageViewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
830				break;
831		}
832
833		de::MovePtr<tcu::TestCaseGroup>	formatGroup(new tcu::TestCaseGroup(testCtx,
834			getFormatCaseName(format).c_str(),
835			(std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
836		createImageCountTests(formatGroup.get(), testCtx, allocationKind, pipelineConstructionType, samplingType, imageViewType, format);
837
838		imageFormatTests->addChild(formatGroup.release());
839	}
840
841	return imageFormatTests;
842}
843
844de::MovePtr<tcu::TestCaseGroup> createImageViewTypeTests (tcu::TestContext& testCtx, AllocationKind allocationKind, PipelineConstructionType pipelineConstructionType, VkDescriptorType samplingType)
845{
846	const struct
847	{
848		VkImageViewType		type;
849		const char*			name;
850	}
851	imageViewTypes[] =
852	{
853		{ VK_IMAGE_VIEW_TYPE_1D,			"1d" },
854		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array" },
855		{ VK_IMAGE_VIEW_TYPE_2D,			"2d" },
856		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array" },
857		{ VK_IMAGE_VIEW_TYPE_3D,			"3d" },
858		{ VK_IMAGE_VIEW_TYPE_CUBE,			"cube" },
859		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array" }
860	};
861
862	de::MovePtr<tcu::TestCaseGroup> imageViewTypeTests(new tcu::TestCaseGroup(testCtx, "view_type"));
863
864	for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
865	{
866		const VkImageViewType			viewType = imageViewTypes[viewTypeNdx].type;
867		de::MovePtr<tcu::TestCaseGroup>	viewTypeGroup(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
868		de::MovePtr<tcu::TestCaseGroup>	formatTests = createImageFormatTests(testCtx, allocationKind, pipelineConstructionType, samplingType, viewType);
869
870		viewTypeGroup->addChild(formatTests.release());
871		imageViewTypeTests->addChild(viewTypeGroup.release());
872	}
873
874	return imageViewTypeTests;
875}
876
877de::MovePtr<tcu::TestCaseGroup> createImageSamplingTypeTests (tcu::TestContext& testCtx, AllocationKind allocationKind, PipelineConstructionType pipelineConstructionType)
878{
879	VkDescriptorType samplingTypes[] =
880	{
881		VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
882		VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
883	};
884
885	de::MovePtr<tcu::TestCaseGroup> imageSamplingTypeTests(new tcu::TestCaseGroup(testCtx, "sampling_type"));
886
887	for (int smpTypeNdx = 0; smpTypeNdx < DE_LENGTH_OF_ARRAY(samplingTypes); smpTypeNdx++)
888	{
889		const char* smpTypeName = samplingTypes[smpTypeNdx] == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? "combined" : "separate";
890		de::MovePtr<tcu::TestCaseGroup>	samplingTypeGroup(new tcu::TestCaseGroup(testCtx, smpTypeName));
891		de::MovePtr<tcu::TestCaseGroup>	viewTypeTests = createImageViewTypeTests(testCtx, allocationKind, pipelineConstructionType, samplingTypes[smpTypeNdx]);
892
893		samplingTypeGroup->addChild(viewTypeTests.release());
894		imageSamplingTypeTests->addChild(samplingTypeGroup.release());
895	}
896
897	return imageSamplingTypeTests;
898}
899
900de::MovePtr<tcu::TestCaseGroup> createSuballocationTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
901{
902	de::MovePtr<tcu::TestCaseGroup>	suballocationTestsGroup(new tcu::TestCaseGroup(testCtx, "suballocation"));
903	de::MovePtr<tcu::TestCaseGroup>	samplingTypeTests = createImageSamplingTypeTests(testCtx, ALLOCATION_KIND_SUBALLOCATED, pipelineConstructionType);
904
905	suballocationTestsGroup->addChild(samplingTypeTests.release());
906
907	return suballocationTestsGroup;
908}
909
910de::MovePtr<tcu::TestCaseGroup> createDedicatedAllocationTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
911{
912	de::MovePtr<tcu::TestCaseGroup>	dedicatedAllocationTestsGroup(new tcu::TestCaseGroup(testCtx, "dedicated_allocation"));
913	de::MovePtr<tcu::TestCaseGroup>	samplingTypeTests = createImageSamplingTypeTests(testCtx, ALLOCATION_KIND_DEDICATED, pipelineConstructionType);
914
915	dedicatedAllocationTestsGroup->addChild(samplingTypeTests.release());
916
917	return dedicatedAllocationTestsGroup;
918}
919} // anonymous
920
921tcu::TestCaseGroup* createImageTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
922{
923	de::MovePtr<tcu::TestCaseGroup> imageTests(new tcu::TestCaseGroup(testCtx, "image"));
924	de::MovePtr<tcu::TestCaseGroup> imageSuballocationTests = createSuballocationTests(testCtx, pipelineConstructionType);
925	de::MovePtr<tcu::TestCaseGroup> imageDedicatedAllocationTests = createDedicatedAllocationTests(testCtx, pipelineConstructionType);
926
927	imageTests->addChild(imageSuballocationTests.release());
928	imageTests->addChild(imageDedicatedAllocationTests.release());
929
930	return imageTests.release();
931}
932
933} // pipeline
934} // vkt
935