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 Sampler Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktPipelineSamplerTests.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 <iomanip>
38#include <sstream>
39#include <vector>
40
41namespace vkt
42{
43namespace pipeline
44{
45
46using namespace vk;
47using de::MovePtr;
48
49namespace
50{
51
52class SamplerTest : public vkt::TestCase
53{
54public:
55										SamplerTest				(tcu::TestContext&	testContext,
56																 const char*		name,
57																 const char*		description,
58																 VkImageViewType	imageViewType,
59																 VkFormat			imageFormat,
60																 int				imageSize,
61																 float				samplerLod);
62	virtual								~SamplerTest			(void) {}
63
64	virtual void						initPrograms			(SourceCollections& sourceCollections) const;
65	virtual TestInstance*				createInstance			(Context& context) const;
66	virtual tcu::UVec2					getRenderSize			(VkImageViewType viewType) const;
67	virtual std::vector<Vertex4Tex4>	createVertices			(void) const;
68	virtual VkSamplerCreateInfo			getSamplerCreateInfo	(void) const;
69
70	static std::string					getGlslSamplerType		(const tcu::TextureFormat& format, VkImageViewType type);
71	static tcu::IVec3					getImageSize			(VkImageViewType viewType, int size);
72	static int							getArraySize			(VkImageViewType viewType);
73
74protected:
75	VkImageViewType						m_imageViewType;
76	VkFormat							m_imageFormat;
77	int									m_imageSize;
78	VkImageViewCreateInfo				m_imageViewParams;
79	VkSamplerCreateInfo					m_samplerParams;
80	float								m_samplerLod;
81};
82
83class SamplerMagFilterTest : public SamplerTest
84{
85public:
86									SamplerMagFilterTest	(tcu::TestContext&	testContext,
87															 const char*		name,
88															 const char*		description,
89															 VkImageViewType	imageViewType,
90															 VkFormat			imageFormat,
91															 VkFilter			magFilter);
92	virtual							~SamplerMagFilterTest	(void) {}
93	virtual VkSamplerCreateInfo		getSamplerCreateInfo	(void) const;
94
95private:
96	VkFilter						m_magFilter;
97};
98
99class SamplerMinFilterTest : public SamplerTest
100{
101public:
102									SamplerMinFilterTest	(tcu::TestContext&	testContext,
103															 const char*		name,
104															 const char*		description,
105															 VkImageViewType	imageViewType,
106															 VkFormat			imageFormat,
107															 VkFilter			minFilter);
108	virtual							~SamplerMinFilterTest	(void) {}
109	virtual VkSamplerCreateInfo		getSamplerCreateInfo	(void) const;
110
111private:
112	VkFilter						m_minFilter;
113};
114
115class SamplerLodTest : public SamplerTest
116{
117public:
118									SamplerLodTest			(tcu::TestContext&		testContext,
119															 const char*			name,
120															 const char*			description,
121															 VkImageViewType		imageViewType,
122															 VkFormat				imageFormat,
123															 VkSamplerMipmapMode	mipmapMode,
124															 float					minLod,
125															 float					maxLod,
126															 float					mipLodBias,
127															 float					samplerLod);
128	virtual							~SamplerLodTest			(void) {}
129	virtual VkSamplerCreateInfo		getSamplerCreateInfo	(void) const;
130
131private:
132	VkSamplerMipmapMode				m_mipmapMode;
133	float							m_minLod;
134	float							m_maxLod;
135	float							m_mipLodBias;
136};
137
138class SamplerAddressModesTest : public SamplerTest
139{
140public:
141										SamplerAddressModesTest		(tcu::TestContext&		testContext,
142																	 const char*			name,
143																	 const char*			description,
144																	 VkImageViewType		imageViewType,
145																	 VkFormat				imageFormat,
146																	 VkSamplerAddressMode	addressU,
147																	 VkSamplerAddressMode	addressV,
148																	 VkSamplerAddressMode	addressW,
149																	 VkBorderColor			borderColor);
150	virtual								~SamplerAddressModesTest	(void) {}
151	virtual tcu::UVec2					getRenderSize				(VkImageViewType viewType) const;
152	virtual std::vector<Vertex4Tex4>	createVertices				(void) const;
153	virtual VkSamplerCreateInfo			getSamplerCreateInfo		(void) const;
154
155private:
156	VkSamplerAddressMode				m_addressU;
157	VkSamplerAddressMode				m_addressV;
158	VkSamplerAddressMode				m_addressW;
159	VkBorderColor						m_borderColor;
160};
161
162
163// SamplerTest
164
165SamplerTest::SamplerTest (tcu::TestContext&	testContext,
166						  const char*		name,
167						  const char*		description,
168						  VkImageViewType	imageViewType,
169						  VkFormat			imageFormat,
170						  int				imageSize,
171						  float				samplerLod)
172	: vkt::TestCase		(testContext, name, description)
173	, m_imageViewType	(imageViewType)
174	, m_imageFormat		(imageFormat)
175	, m_imageSize		(imageSize)
176	, m_samplerLod		(samplerLod)
177{
178}
179
180void SamplerTest::initPrograms (SourceCollections& sourceCollections) const
181{
182	std::ostringstream				vertexSrc;
183	std::ostringstream				fragmentSrc;
184	const char*						texCoordSwizzle	= DE_NULL;
185	tcu::TextureFormat				format			= (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat))
186																						  : mapVkFormat(m_imageFormat);
187	tcu::Vec4						lookupScale;
188	tcu::Vec4						lookupBias;
189
190	getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
191
192	switch (m_imageViewType)
193	{
194		case VK_IMAGE_VIEW_TYPE_1D:
195			texCoordSwizzle = "x";
196			break;
197		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
198		case VK_IMAGE_VIEW_TYPE_2D:
199			texCoordSwizzle = "xy";
200			break;
201		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
202		case VK_IMAGE_VIEW_TYPE_3D:
203		case VK_IMAGE_VIEW_TYPE_CUBE:
204			texCoordSwizzle = "xyz";
205			break;
206		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
207			texCoordSwizzle = "xyzw";
208			break;
209		default:
210			DE_ASSERT(false);
211			break;
212	}
213
214	vertexSrc << "#version 440\n"
215			  << "layout(location = 0) in vec4 position;\n"
216			  << "layout(location = 1) in vec4 texCoords;\n"
217			  << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
218			  << "out gl_PerVertex {\n"
219			  << "	vec4 gl_Position;\n"
220			  << "};\n"
221			  << "void main (void)\n"
222			  << "{\n"
223			  << "	gl_Position = position;\n"
224			  << "	vtxTexCoords = texCoords;\n"
225			  << "}\n";
226
227	fragmentSrc << "#version 440\n"
228				<< "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n"
229				<< "layout(location = 0) in highp vec4 vtxTexCoords;\n"
230				<< "layout(location = 0) out highp vec4 fragColor;\n"
231				<< "void main (void)\n"
232				<< "{\n"
233				<< "	fragColor = ";
234
235	if (m_samplerLod > 0.0f)
236		fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed <<  m_samplerLod << ")";
237	else
238		fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
239
240	fragmentSrc << " * vec4" << std::scientific << lookupScale << " + vec4" << lookupBias << ";\n"
241				<< "}\n";
242
243	sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
244	sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
245}
246
247TestInstance* SamplerTest::createInstance (Context& context) const
248{
249	const tcu::UVec2				renderSize			= getRenderSize(m_imageViewType);
250	const std::vector<Vertex4Tex4>	vertices			= createVertices();
251	const VkSamplerCreateInfo		samplerParams		= getSamplerCreateInfo();
252	const VkComponentMapping		componentMapping	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
253	const VkImageSubresourceRange	subresourceRange	=
254	{
255		VK_IMAGE_ASPECT_COLOR_BIT,								// VkImageAspectFlags	aspectMask;
256		0u,														// deUint32				baseMipLevel;
257		(deUint32)deLog2Floor32(m_imageSize) + 1,				// deUint32				mipLevels;
258		0u,														// deUint32				baseArrayLayer;
259		(deUint32)SamplerTest::getArraySize(m_imageViewType)	// deUint32				arraySize;
260	};
261
262
263
264	return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat,
265									 getImageSize(m_imageViewType, m_imageSize),
266									 getArraySize(m_imageViewType),
267									 componentMapping, subresourceRange,
268									 samplerParams, m_samplerLod,vertices);
269}
270
271tcu::UVec2 SamplerTest::getRenderSize (VkImageViewType viewType) const
272{
273	if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
274	{
275		return tcu::UVec2(16u, 16u);
276	}
277	else
278	{
279		return tcu::UVec2(16u * 3u, 16u * 2u);
280	}
281}
282
283std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const
284{
285	std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
286	// Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries.
287	// TODO: Would be nice to base this on number of texels and subtexel precision. But this
288	// seems to work.
289	for (unsigned int i = 0; i < vertices.size(); ++i) {
290		vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f);
291	}
292	return vertices;
293}
294
295VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const
296{
297	const VkSamplerCreateInfo defaultSamplerParams =
298	{
299		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,									// VkStructureType			sType;
300		DE_NULL,																// const void*				pNext;
301		0u,																		// VkSamplerCreateFlags		flags;
302		VK_FILTER_NEAREST,														// VkFilter					magFilter;
303		VK_FILTER_NEAREST,														// VkFilter					minFilter;
304		VK_SAMPLER_MIPMAP_MODE_NEAREST,											// VkSamplerMipmapMode		mipmapMode;
305		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,									// VkSamplerAddressMode		addressModeU;
306		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,									// VkSamplerAddressMode		addressModeV;
307		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,									// VkSamplerAddressMode		addressModeW;
308		0.0f,																	// float					mipLodBias;
309		VK_FALSE,																// VkBool32					anisotropyEnable;
310		1.0f,																	// float					maxAnisotropy;
311		false,																	// VkBool32					compareEnable;
312		VK_COMPARE_OP_NEVER,													// VkCompareOp				compareOp;
313		0.0f,																	// float					minLod;
314		0.25f,																	// float					maxLod;
315		getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat),	// VkBorderColor			borderColor;
316		false																	// VkBool32					unnormalizedCoordinates;
317	};
318
319	return defaultSamplerParams;
320}
321
322std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type)
323{
324	std::ostringstream samplerType;
325
326	if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
327		samplerType << "u";
328	else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
329		samplerType << "i";
330
331	switch (type)
332	{
333		case VK_IMAGE_VIEW_TYPE_1D:
334			samplerType << "sampler1D";
335			break;
336
337		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
338			samplerType << "sampler1DArray";
339			break;
340
341		case VK_IMAGE_VIEW_TYPE_2D:
342			samplerType << "sampler2D";
343			break;
344
345		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
346			samplerType << "sampler2DArray";
347			break;
348
349		case VK_IMAGE_VIEW_TYPE_3D:
350			samplerType << "sampler3D";
351			break;
352
353		case VK_IMAGE_VIEW_TYPE_CUBE:
354			samplerType << "samplerCube";
355			break;
356
357		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
358			samplerType << "samplerCubeArray";
359			break;
360
361		default:
362			DE_FATAL("Unknown image view type");
363			break;
364	}
365
366	return samplerType.str();
367}
368
369tcu::IVec3 SamplerTest::getImageSize (VkImageViewType viewType, int size)
370{
371	switch (viewType)
372	{
373		case VK_IMAGE_VIEW_TYPE_1D:
374		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
375			return tcu::IVec3(size, 1, 1);
376
377		case VK_IMAGE_VIEW_TYPE_3D:
378			return tcu::IVec3(size, size, 4);
379
380		default:
381			break;
382	}
383
384	return tcu::IVec3(size, size, 1);
385}
386
387int SamplerTest::getArraySize (VkImageViewType viewType)
388{
389	switch (viewType)
390	{
391		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
392		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
393		case VK_IMAGE_VIEW_TYPE_CUBE:
394			return 6;
395
396		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
397			return 36;
398
399		default:
400			break;
401	}
402
403	return 1;
404}
405
406
407// SamplerMagFilterTest
408
409SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext&	testContext,
410											const char*			name,
411											const char*			description,
412											VkImageViewType		imageViewType,
413											VkFormat			imageFormat,
414											VkFilter			magFilter)
415	: SamplerTest	(testContext, name, description, imageViewType, imageFormat, 8, 0.0f)
416	, m_magFilter	(magFilter)
417{
418}
419
420VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const
421{
422	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
423	samplerParams.magFilter = m_magFilter;
424
425	return samplerParams;
426}
427
428
429// SamplerMinFilterTest
430
431SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext&	testContext,
432											const char*			name,
433											const char*			description,
434											VkImageViewType		imageViewType,
435											VkFormat			imageFormat,
436											VkFilter			minFilter)
437	: SamplerTest	(testContext, name, description, imageViewType, imageFormat, 32, 0.0f)
438	, m_minFilter	(minFilter)
439{
440}
441
442VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const
443{
444	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
445	samplerParams.minFilter = m_minFilter;
446	// set minLod to epsilon, to force use of the minFilter
447	samplerParams.minLod = 0.01f;
448
449	return samplerParams;
450}
451
452
453// SamplerLodTest
454
455SamplerLodTest::SamplerLodTest (tcu::TestContext&	testContext,
456								const char*			name,
457								const char*			description,
458								VkImageViewType		imageViewType,
459								VkFormat			imageFormat,
460								VkSamplerMipmapMode	mipmapMode,
461								float				minLod,
462								float				maxLod,
463								float				mipLodBias,
464								float				samplerLod)
465	: SamplerTest	(testContext, name, description, imageViewType, imageFormat, 32, samplerLod)
466	, m_mipmapMode	(mipmapMode)
467	, m_minLod		(minLod)
468	, m_maxLod		(maxLod)
469	, m_mipLodBias	(mipLodBias)
470{
471}
472
473VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const
474{
475	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
476
477	samplerParams.mipmapMode	= m_mipmapMode;
478	samplerParams.minLod		= m_minLod;
479	samplerParams.maxLod		= m_maxLod;
480	samplerParams.mipLodBias	= m_mipLodBias;
481
482	return samplerParams;
483}
484
485
486// SamplerAddressModesTest
487
488SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext&		testContext,
489												  const char*			name,
490												  const char*			description,
491												  VkImageViewType		imageViewType,
492												  VkFormat				imageFormat,
493												  VkSamplerAddressMode	addressU,
494												  VkSamplerAddressMode	addressV,
495												  VkSamplerAddressMode	addressW,
496												  VkBorderColor			borderColor)
497	: SamplerTest	(testContext, name, description, imageViewType, imageFormat, 8, 0.0f)
498	, m_addressU	(addressU)
499	, m_addressV	(addressV)
500	, m_addressW	(addressW)
501	, m_borderColor	(borderColor)
502{
503}
504
505tcu::UVec2 SamplerAddressModesTest::getRenderSize (VkImageViewType viewType) const
506{
507	return 4u * SamplerTest::getRenderSize(viewType);
508}
509
510std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const
511{
512	std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
513
514	switch (m_imageViewType)
515	{
516		case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
517			for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
518				vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
519
520			break;
521
522		case VK_IMAGE_VIEW_TYPE_2D:
523		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
524			for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
525				vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
526
527			break;
528
529		case VK_IMAGE_VIEW_TYPE_3D:
530			for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
531				vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
532
533			break;
534
535		case VK_IMAGE_VIEW_TYPE_CUBE:
536		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
537			break;
538
539		default:
540			DE_ASSERT(false);
541	}
542
543	return vertices;
544}
545
546VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const
547{
548	VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
549	samplerParams.addressModeU	= m_addressU;
550	samplerParams.addressModeV	= m_addressV;
551	samplerParams.addressModeW	= m_addressW;
552	samplerParams.borderColor	= m_borderColor;
553
554	return samplerParams;
555}
556
557
558// Utilities to create test nodes
559
560std::string getFormatCaseName (const VkFormat format)
561{
562	const std::string fullName = getFormatName(format);
563
564	DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
565
566	return de::toLower(fullName.substr(10));
567}
568
569MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
570{
571	MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter"));
572
573	if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
574		samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR));
575	samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST));
576
577	return samplerMagFilterTests;
578}
579
580MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
581{
582	MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter"));
583
584	if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
585		samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR));
586	samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST));
587
588	return samplerMinFilterTests;
589}
590
591MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode)
592{
593	struct TestCaseConfig
594	{
595		const char*	name;
596		const char*	description;
597		float		minLod;
598		float		maxLod;
599		float		mipLodBias;
600		float		lod;
601	};
602
603	TestCaseConfig testCaseConfigs [] =
604	{
605		{ "equal_min_3_max_3",		"minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0",		3.0f, 3.0f, 0.0f, 0.0f },
606		{ "select_min_1",			"minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0",		1.0f, 5.0f, 0.0f, 0.0f },
607		{ "select_max_4",			"minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5",		0.0f, 4.0f, 0.0f, 5.0f },
608		{ "select_bias_2_1",		"minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0",	0.0f, 2.1f, 5.0f, 0.0f },
609		{ "select_bias_2_5",		"minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0",	0.0f, 5.0f, 2.5f, 0.00001f },
610		{ "select_bias_3_1",		"minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0",	0.0f, 5.0f, -0.9f, 4.0f },
611		{ "select_bias_3_7",		"minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7",	0.0f, 5.0f, 3.0f, 0.7f },
612	};
613
614	MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD"));
615
616	for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
617	{
618		const TestCaseConfig& config = testCaseConfigs[configNdx];
619
620		samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod));
621	}
622
623	return samplerLodTests;
624}
625
626MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
627{
628	MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes"));
629
630	// Mipmap mode: nearest
631	MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST"));
632	mipmapNearestTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST).release());
633	samplerMipmapTests->addChild(mipmapNearestTests.release());
634
635	// Mipmap mode: linear
636	if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
637	{
638		MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR"));
639		mipmapLinearTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR).release());
640		samplerMipmapTests->addChild(mipmapLinearTests.release());
641	}
642
643	return samplerMipmapTests;
644}
645
646std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border)
647{
648	static const char* borderColorNames[BORDER_COLOR_COUNT] =
649	{
650		"opaque_black",
651		"opaque_white",
652		"transparent_black",
653	};
654
655	std::ostringstream caseName;
656
657	if (u == v && v == w)
658	{
659		const std::string fullName = getSamplerAddressModeName(u);
660		DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
661
662		caseName << "all_";
663		caseName << de::toLower(fullName.substr(19));
664
665		if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
666		{
667			caseName << "_" << borderColorNames[border];
668		}
669	}
670	else
671	{
672		const std::string fullNameU = getSamplerAddressModeName(u);
673		const std::string fullNameV = getSamplerAddressModeName(v);
674		const std::string fullNameW = getSamplerAddressModeName(w);
675
676		DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
677		DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
678		DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
679
680		caseName << "uvw"
681				 << "_" << de::toLower(fullNameU.substr(19))
682				 << "_" << de::toLower(fullNameV.substr(19))
683				 << "_" << de::toLower(fullNameW.substr(19));
684	}
685
686	return caseName.str();
687}
688
689MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat)
690{
691	struct TestCaseConfig
692	{
693		VkSamplerAddressMode	u;
694		VkSamplerAddressMode	v;
695		VkSamplerAddressMode	w;
696		BorderColor				border;
697	};
698
699	const TestCaseConfig testCaseConfigs[] =
700	{
701		// All address modes equal
702		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_TRANSPARENT_BLACK },
703		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_TRANSPARENT_BLACK },
704		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_TRANSPARENT_BLACK },
705		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_TRANSPARENT_BLACK },
706
707		// All address modes equal using border color
708		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_TRANSPARENT_BLACK },
709		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_BLACK },
710		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
711
712		// Pairwise combinations of address modes not covered by previous tests
713		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE},
714		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
715		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
716		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
717		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
718		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
719		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE },
720		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
721		{ VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
722		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
723		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
724		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
725		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE },
726		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
727		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
728		{ VK_SAMPLER_ADDRESS_MODE_REPEAT,				VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
729		{ VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
730		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		BORDER_COLOR_OPAQUE_WHITE },
731		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					BORDER_COLOR_OPAQUE_WHITE },
732		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_REPEAT,					VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	BORDER_COLOR_OPAQUE_WHITE },
733		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,			BORDER_COLOR_OPAQUE_WHITE },
734		{ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,	VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,		BORDER_COLOR_OPAQUE_WHITE },
735	};
736
737	MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes"));
738
739	for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
740	{
741		const TestCaseConfig& config = testCaseConfigs[configNdx];
742
743		samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx,
744																	   getAddressModesCaseName(config.u, config.v, config.w, config.border).c_str(),
745																	   "",
746																	   imageViewType,
747																	   imageFormat,
748																	   config.u, config.v, config.w,
749																	   getFormatBorderColor(config.border, imageFormat)));
750	}
751
752	return samplerAddressModesTests;
753}
754
755} // anonymous
756
757tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx)
758{
759	const struct
760	{
761		VkImageViewType		type;
762		const char*			name;
763	}
764	imageViewTypes[] =
765	{
766		{ VK_IMAGE_VIEW_TYPE_1D,			"1d" },
767		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		"1d_array" },
768		{ VK_IMAGE_VIEW_TYPE_2D,			"2d" },
769		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		"2d_array" },
770		{ VK_IMAGE_VIEW_TYPE_3D,			"3d" },
771		{ VK_IMAGE_VIEW_TYPE_CUBE,			"cube" },
772		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	"cube_array" }
773	};
774
775	const VkFormat formats[] =
776	{
777		// Packed formats
778		VK_FORMAT_R4G4_UNORM_PACK8,
779		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
780		VK_FORMAT_R5G6B5_UNORM_PACK16,
781		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
782		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
783		VK_FORMAT_A2R10G10B10_UINT_PACK32,
784		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
785		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
786		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
787		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
788
789		// Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
790		VK_FORMAT_R8_SRGB,
791		VK_FORMAT_R8G8B8_UINT,
792		VK_FORMAT_B8G8R8A8_SINT,
793		VK_FORMAT_R8G8_UNORM,
794		VK_FORMAT_B8G8R8_SNORM,
795		VK_FORMAT_R8G8B8A8_SNORM,
796		VK_FORMAT_R8G8_UINT,
797		VK_FORMAT_R8_SINT,
798		VK_FORMAT_R8G8B8A8_SRGB,
799		VK_FORMAT_R8G8B8A8_UNORM,
800		VK_FORMAT_B8G8R8A8_UNORM,
801		VK_FORMAT_B8G8R8_SRGB,
802		VK_FORMAT_R8G8_SRGB,
803		VK_FORMAT_R8_UINT,
804		VK_FORMAT_R8G8B8A8_UINT,
805		VK_FORMAT_R8G8_SINT,
806		VK_FORMAT_R8_SNORM,
807		VK_FORMAT_B8G8R8_SINT,
808		VK_FORMAT_R8G8_SNORM,
809		VK_FORMAT_B8G8R8_UNORM,
810		VK_FORMAT_R8_UNORM,
811
812		// Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
813		VK_FORMAT_R32G32_SFLOAT,
814		VK_FORMAT_R32G32B32_UINT,
815		VK_FORMAT_R16G16B16A16_SFLOAT,
816		VK_FORMAT_R16G16_UINT,
817		VK_FORMAT_R32G32B32A32_SINT,
818		VK_FORMAT_R16G16B16_SINT,
819		VK_FORMAT_R16_SFLOAT,
820		VK_FORMAT_R32_SINT,
821		VK_FORMAT_R32_UINT,
822		VK_FORMAT_R16G16B16_SFLOAT,
823		VK_FORMAT_R16G16_SINT,
824
825		// Scaled formats
826		VK_FORMAT_R8G8B8A8_SSCALED,
827		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
828
829		// Compressed formats
830		VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
831		VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
832		VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
833		VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
834		VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
835		VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
836		VK_FORMAT_EAC_R11_UNORM_BLOCK,
837		VK_FORMAT_EAC_R11_SNORM_BLOCK,
838		VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
839		VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
840		VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
841		VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
842		VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
843		VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
844		VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
845		VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
846		VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
847		VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
848		VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
849		VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
850	};
851
852	de::MovePtr<tcu::TestCaseGroup> samplerTests		(new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests"));
853	de::MovePtr<tcu::TestCaseGroup> viewTypeTests		(new tcu::TestCaseGroup(testCtx, "view_type", ""));
854
855	for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
856	{
857		const VkImageViewType			viewType		= imageViewTypes[viewTypeNdx].type;
858		de::MovePtr<tcu::TestCaseGroup>	viewTypeGroup	(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str()));
859		de::MovePtr<tcu::TestCaseGroup>	formatTests		(new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats"));
860
861		for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
862		{
863			const VkFormat	format			= formats[formatNdx];
864			const bool		isCompressed	= isCompressedFormat(format);
865
866			if (isCompressed)
867			{
868				// Do not use compressed formats with 1D and 1D array textures.
869				if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
870					break;
871			}
872
873			de::MovePtr<tcu::TestCaseGroup>	formatGroup	(new tcu::TestCaseGroup(testCtx,
874																				getFormatCaseName(format).c_str(),
875																				(std::string("Samples a texture of format ") + getFormatName(format)).c_str()));
876
877			if (!isCompressed)
878			{
879				// Do not include minFilter tests with compressed formats.
880				// Randomly generated compressed textures are too noisy and will derive in false positives.
881				de::MovePtr<tcu::TestCaseGroup>	minFilterTests		= createSamplerMinFilterTests(testCtx, viewType, format);
882				formatGroup->addChild(minFilterTests.release());
883			}
884
885			de::MovePtr<tcu::TestCaseGroup>	magFilterTests		= createSamplerMagFilterTests(testCtx, viewType, format);
886			de::MovePtr<tcu::TestCaseGroup>	mipmapTests			= createSamplerMipmapTests(testCtx, viewType, format);
887
888			formatGroup->addChild(magFilterTests.release());
889			formatGroup->addChild(mipmapTests.release());
890
891			if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
892			{
893				de::MovePtr<tcu::TestCaseGroup>	addressModesTests	= createSamplerAddressModesTests(testCtx, viewType, format);
894				formatGroup->addChild(addressModesTests.release());
895			}
896
897			formatTests->addChild(formatGroup.release());
898		}
899
900		viewTypeGroup->addChild(formatTests.release());
901		viewTypeTests->addChild(viewTypeGroup.release());
902	}
903
904	samplerTests->addChild(viewTypeTests.release());
905
906	return samplerTests.release();
907}
908
909} // pipeline
910} // vkt
911