1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Mipmapping tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktTextureMipmapTests.hpp"
27 
28 #include "deRandom.hpp"
29 #include "deString.h"
30 #include "gluShaderUtil.hpp"
31 #include "gluTextureTestUtil.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuMatrixUtil.hpp"
34 #include "tcuPixelFormat.hpp"
35 #include "tcuTexLookupVerifier.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuVectorUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vktTestGroupUtil.hpp"
40 #include "vktTextureTestUtil.hpp"
41 
42 using namespace vk;
43 
44 namespace vkt
45 {
46 namespace texture
47 {
48 namespace
49 {
50 
51 using std::string;
52 using std::vector;
53 using tcu::TestLog;
54 using tcu::Vec2;
55 using tcu::Vec3;
56 using tcu::Vec4;
57 using tcu::IVec4;
58 using tcu::Sampler;
59 using tcu::TextureFormat;
60 using namespace texture::util;
61 using namespace glu::TextureTestUtil;
62 
getMinLodForCell(int cellNdx)63 float getMinLodForCell (int cellNdx)
64 {
65 	static const float s_values[] =
66 	{
67 		1.0f,
68 		3.5f,
69 		2.0f,
70 		-2.0f,
71 		0.0f,
72 		3.0f,
73 		10.0f,
74 		4.8f,
75 		5.8f,
76 		5.7f,
77 		-1.9f,
78 		4.0f,
79 		6.5f,
80 		7.1f,
81 		-1e10,
82 		1000.f
83 	};
84 	return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
85 }
86 
getMaxLodForCell(int cellNdx)87 float getMaxLodForCell (int cellNdx)
88 {
89 	static const float s_values[] =
90 	{
91 		0.0f,
92 		0.2f,
93 		0.7f,
94 		0.4f,
95 		1.3f,
96 		0.0f,
97 		0.5f,
98 		1.2f,
99 		-2.0f,
100 		1.0f,
101 		0.1f,
102 		0.3f,
103 		2.7f,
104 		1.2f,
105 		10.0f,
106 		-1000.f,
107 		1e10f
108 	};
109 	return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
110 }
111 
112 enum CoordType
113 {
114 	COORDTYPE_BASIC,		//!< texCoord = translateScale(position).
115 	COORDTYPE_BASIC_BIAS,	//!< Like basic, but with bias values.
116 	COORDTYPE_AFFINE,		//!< texCoord = translateScaleRotateShear(position).
117 	COORDTYPE_PROJECTED,	//!< Projected coordinates, w != 1
118 
119 	COORDTYPE_LAST
120 };
121 
122 struct TextureMipmapCommonTestCaseParameters
123 {
124 							TextureMipmapCommonTestCaseParameters		(void);
125 	CoordType				coordType;
126 	const char*				minFilterName;
127 };
128 
TextureMipmapCommonTestCaseParameters(void)129 TextureMipmapCommonTestCaseParameters::TextureMipmapCommonTestCaseParameters (void)
130 	: coordType				(COORDTYPE_BASIC)
131 	, minFilterName			(NULL)
132 {
133 }
134 
135 struct Texture2DMipmapTestCaseParameters : public Texture2DTestCaseParameters, public TextureMipmapCommonTestCaseParameters
136 {
137 };
138 
139 struct TextureCubeMipmapTestCaseParameters : public TextureCubeTestCaseParameters, public TextureMipmapCommonTestCaseParameters
140 {
141 };
142 
143 struct Texture3DMipmapTestCaseParameters : public Texture3DTestCaseParameters, public TextureMipmapCommonTestCaseParameters
144 {
145 };
146 
147 // Texture2DMipmapTestInstance
148 class Texture2DMipmapTestInstance : public TestInstance
149 {
150 public:
151 	typedef Texture2DMipmapTestCaseParameters	ParameterType;
152 
153 									Texture2DMipmapTestInstance		(Context& context, const ParameterType& testParameters);
154 									~Texture2DMipmapTestInstance	(void);
155 
156 	virtual tcu::TestStatus			iterate							(void);
157 
158 private:
159 									Texture2DMipmapTestInstance		(const Texture2DMipmapTestInstance& other);
160 	Texture2DMipmapTestInstance&	operator=						(const Texture2DMipmapTestInstance& other);
161 
162 	const ParameterType				m_testParameters;
163 	TestTexture2DSp					m_texture;
164 	TextureRenderer					m_renderer;
165 };
166 
Texture2DMipmapTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)167 Texture2DMipmapTestInstance::Texture2DMipmapTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
168 	: TestInstance		(context)
169 	, m_testParameters	(testParameters)
170 	, m_renderer		(context, testParameters.sampleCount, testParameters.width*4, testParameters.height*4)
171 {
172 	TCU_CHECK_INTERNAL(!(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
173 
174 	m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height));
175 
176 	const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1;
177 
178 	// Fill texture with colored grid.
179 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
180 	{
181 		const deUint32	step	= 0xff / (numLevels-1);
182 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
183 		const deUint32	dec		= 0xff - inc;
184 		const deUint32	rgb		= (inc << 16) | (dec << 8) | 0xff;
185 		const deUint32	color	= 0xff000000 | rgb;
186 
187 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
188 	}
189 
190 	// Upload texture data.
191 	m_renderer.add2DTexture(m_texture);
192 }
193 
~Texture2DMipmapTestInstance(void)194 Texture2DMipmapTestInstance::~Texture2DMipmapTestInstance (void)
195 {
196 }
197 
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)198 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
199 {
200 	static const struct
201 	{
202 		const Vec2	bottomLeft;
203 		const Vec2	topRight;
204 	} s_basicCoords[] =
205 	{
206 		{ Vec2(-0.1f,  0.1f), Vec2( 0.8f,  1.0f) },
207 		{ Vec2(-0.3f, -0.6f), Vec2( 0.7f,  0.4f) },
208 		{ Vec2(-0.3f,  0.6f), Vec2( 0.7f, -0.9f) },
209 		{ Vec2(-0.8f,  0.6f), Vec2( 0.7f, -0.9f) },
210 
211 		{ Vec2(-0.5f, -0.5f), Vec2( 1.5f,  1.5f) },
212 		{ Vec2( 1.0f, -1.0f), Vec2(-1.3f,  1.0f) },
213 		{ Vec2( 1.2f, -1.0f), Vec2(-1.3f,  1.6f) },
214 		{ Vec2( 2.2f, -1.1f), Vec2(-1.3f,  0.8f) },
215 
216 		{ Vec2(-1.5f,  1.6f), Vec2( 1.7f, -1.4f) },
217 		{ Vec2( 2.0f,  1.6f), Vec2( 2.3f, -1.4f) },
218 		{ Vec2( 1.3f, -2.6f), Vec2(-2.7f,  2.9f) },
219 		{ Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },
220 
221 		{ Vec2( -8.0f,   9.0f), Vec2(  8.3f,  -7.0f) },
222 		{ Vec2(-16.0f,  10.0f), Vec2( 18.3f,  24.0f) },
223 		{ Vec2( 30.2f,  55.0f), Vec2(-24.3f,  -1.6f) },
224 		{ Vec2(-33.2f,  64.1f), Vec2( 32.1f, -64.1f) },
225 	};
226 
227 	DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
228 
229 	const Vec2& bottomLeft	= s_basicCoords[cellNdx].bottomLeft;
230 	const Vec2& topRight	= s_basicCoords[cellNdx].topRight;
231 
232 	computeQuadTexCoord2D(dst, bottomLeft, topRight);
233 }
234 
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)235 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
236 {
237 	// Use basic coords as base.
238 	getBasicTexCoord2D(dst, cellNdx);
239 
240 	// Rotate based on cell index.
241 	const float		angle		= 2.0f*DE_PI * ((float)cellNdx / 16.0f);
242 	const tcu::Mat2	rotMatrix	= tcu::rotationMatrix(angle);
243 
244 	// Second and third row are sheared.
245 	const float		shearX		= de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
246 	const tcu::Mat2	shearMatrix	= tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
247 
248 	const tcu::Mat2	transform	= rotMatrix * shearMatrix;
249 	const Vec2		p0			= transform * Vec2(dst[0], dst[1]);
250 	const Vec2		p1			= transform * Vec2(dst[2], dst[3]);
251 	const Vec2		p2			= transform * Vec2(dst[4], dst[5]);
252 	const Vec2		p3			= transform * Vec2(dst[6], dst[7]);
253 
254 	dst[0] = p0.x();	dst[1] = p0.y();
255 	dst[2] = p1.x();	dst[3] = p1.y();
256 	dst[4] = p2.x();	dst[5] = p2.y();
257 	dst[6] = p3.x();	dst[7] = p3.y();
258 }
259 
iterate(void)260 tcu::TestStatus Texture2DMipmapTestInstance::iterate (void)
261 {
262 	const Sampler::FilterMode	magFilter		= Sampler::NEAREST;
263 	const int					viewportWidth	= m_renderer.getRenderWidth();
264 	const int					viewportHeight	= m_renderer.getRenderHeight();
265 
266 	ReferenceParams				refParams		(TEXTURETYPE_2D);
267 	vector<float>				texCoord;
268 
269 	const bool					isProjected		= m_testParameters.coordType == COORDTYPE_PROJECTED;
270 	const bool					useLodBias		= m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
271 
272 	tcu::Surface				renderedFrame	(viewportWidth, viewportHeight);
273 
274 	// Viewport is divided into 4x4 grid.
275 	const int					gridWidth		= 4;
276 	const int					gridHeight		= 4;
277 	const int					cellWidth		= viewportWidth / gridWidth;
278 	const int					cellHeight		= viewportHeight / gridHeight;
279 
280 	// Sampling parameters.
281 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
282 	refParams.samplerType	= getSamplerType(vk::mapVkFormat(m_testParameters.format));
283 	refParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
284 	refParams.lodMode		= LODMODE_EXACT; // Use ideal lod.
285 
286 	// Bias values.
287 	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
288 
289 	// Projection values.
290 	static const Vec4 s_projections[] =
291 	{
292 		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
293 		Vec4(1.3f, 0.8f, 0.6f, 2.0f),
294 		Vec4(0.8f, 1.0f, 1.7f, 0.6f),
295 		Vec4(1.2f, 1.0f, 1.7f, 1.5f)
296 	};
297 
298 	// Render cells.
299 	for (int gridY = 0; gridY < gridHeight; gridY++)
300 	{
301 		for (int gridX = 0; gridX < gridWidth; gridX++)
302 		{
303 			const int	curX		= cellWidth*gridX;
304 			const int	curY		= cellHeight*gridY;
305 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
306 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
307 			const int	cellNdx		= gridY*gridWidth + gridX;
308 
309 			// Compute texcoord.
310 			switch (m_testParameters.coordType)
311 			{
312 				case COORDTYPE_BASIC_BIAS:	// Fall-through.
313 				case COORDTYPE_PROJECTED:
314 				case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
315 				case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
316 				default:					DE_ASSERT(DE_FALSE);
317 			}
318 
319 			if (isProjected)
320 				refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
321 
322 			if (useLodBias)
323 				refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
324 
325 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
326 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
327 		}
328 	}
329 
330 	// Compare and log.
331 	{
332 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
333 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
334 		const bool				isTrilinear		= m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
335 		tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
336 		tcu::Surface			errorMask		(viewportWidth, viewportHeight);
337 		tcu::LookupPrecision	lookupPrec;
338 		tcu::LodPrecision		lodPrec;
339 		int						numFailedPixels	= 0;
340 
341 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
342 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
343 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
344 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
345 		lodPrec.derivateBits		= 10;
346 		lodPrec.lodBits				= isProjected ? 6 : 8;
347 
348 		for (int gridY = 0; gridY < gridHeight; gridY++)
349 		{
350 			for (int gridX = 0; gridX < gridWidth; gridX++)
351 			{
352 				const int	curX		= cellWidth*gridX;
353 				const int	curY		= cellHeight*gridY;
354 				const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
355 				const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
356 				const int	cellNdx		= gridY*gridWidth + gridX;
357 
358 				// Compute texcoord.
359 				switch (m_testParameters.coordType)
360 				{
361 					case COORDTYPE_BASIC_BIAS:	// Fall-through.
362 					case COORDTYPE_PROJECTED:
363 					case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
364 					case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
365 					default:					DE_ASSERT(DE_FALSE);
366 				}
367 
368 				if (isProjected)
369 					refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
370 
371 				if (useLodBias)
372 					refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
373 
374 				// Render ideal result
375 				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
376 							  m_texture->getTexture(), &texCoord[0], refParams);
377 
378 				// Compare this cell
379 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
380 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
381 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
382 															m_texture->getTexture(), &texCoord[0], refParams,
383 															lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
384 			}
385 		}
386 
387 		if (numFailedPixels > 0)
388 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
389 
390 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
391 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
392 
393 		if (numFailedPixels > 0)
394 		{
395 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
396 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
397 		}
398 
399 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
400 
401 		{
402 			const bool isOk = numFailedPixels == 0;
403 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
404 		}
405 	}
406 }
407 
408 // TextureCubeMipmapTestInstance
409 class TextureCubeMipmapTestInstance : public TestInstance
410 {
411 public:
412 	typedef	TextureCubeMipmapTestCaseParameters	ParameterType;
413 
414 									TextureCubeMipmapTestInstance	(Context& context, const ParameterType& testParameters);
415 									~TextureCubeMipmapTestInstance	(void);
416 
417 	virtual tcu::TestStatus			iterate							(void);
418 
419 private:
420 									TextureCubeMipmapTestInstance	(const TextureCubeMipmapTestInstance& other);
421 	TextureCubeMipmapTestInstance&	operator=						(const TextureCubeMipmapTestInstance& other);
422 
423 	const ParameterType				m_testParameters;
424 	TestTextureCubeSp				m_texture;
425 	TextureRenderer					m_renderer;
426 };
427 
TextureCubeMipmapTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)428 TextureCubeMipmapTestInstance::TextureCubeMipmapTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
429 	: TestInstance		(context)
430 	, m_testParameters	(testParameters)
431 	, m_renderer		(context, m_testParameters.sampleCount, m_testParameters.size*2, m_testParameters.size*2)
432 {
433 	TCU_CHECK_INTERNAL(!(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
434 
435 	m_texture = TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size));
436 
437 	const int numLevels = deLog2Floor32(m_testParameters.size)+1;
438 
439 	// Fill texture with colored grid.
440 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
441 	{
442 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
443 		{
444 			const deUint32	step	= 0xff / (numLevels-1);
445 			const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
446 			const deUint32	dec		= 0xff - inc;
447 			deUint32		rgb		= 0;
448 
449 			switch (faceNdx)
450 			{
451 				case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
452 				case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
453 				case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
454 				case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
455 				case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
456 				case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
457 			}
458 
459 			const deUint32	color	= 0xff000000 | rgb;
460 			tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
461 		}
462 	}
463 
464 	m_renderer.addCubeTexture(m_texture);
465 }
466 
~TextureCubeMipmapTestInstance(void)467 TextureCubeMipmapTestInstance::~TextureCubeMipmapTestInstance (void)
468 {
469 }
470 
randomPartition(vector<IVec4> & dst,de::Random & rnd,int x,int y,int width,int height)471 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
472 {
473 	const int	minWidth	= 8;
474 	const int	minHeight	= 8;
475 
476 	const bool	partition	= rnd.getFloat() > 0.4f;
477 	const bool	partitionX	= partition && width > minWidth && rnd.getBool();
478 	const bool	partitionY	= partition && height > minHeight && !partitionX;
479 
480 	if (partitionX)
481 	{
482 		const int split = width/2 + rnd.getInt(-width/4, +width/4);
483 		randomPartition(dst, rnd, x, y, split, height);
484 		randomPartition(dst, rnd, x+split, y, width-split, height);
485 	}
486 	else if (partitionY)
487 	{
488 		const int split = height/2 + rnd.getInt(-height/4, +height/4);
489 		randomPartition(dst, rnd, x, y, width, split);
490 		randomPartition(dst, rnd, x, y+split, width, height-split);
491 	}
492 	else
493 		dst.push_back(IVec4(x, y, width, height));
494 }
495 
computeGridLayout(vector<IVec4> & dst,int width,int height)496 static void computeGridLayout (vector<IVec4>& dst, int width, int height)
497 {
498 	de::Random rnd(7);
499 	randomPartition(dst, rnd, 0, 0, width, height);
500 }
501 
iterate(void)502 tcu::TestStatus TextureCubeMipmapTestInstance::iterate (void)
503 {
504 	const int			viewportWidth	= m_renderer.getRenderWidth();
505 	const int			viewportHeight	= m_renderer.getRenderHeight();
506 
507 	const bool			isProjected		= m_testParameters.coordType == COORDTYPE_PROJECTED;
508 	const bool			useLodBias		= m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
509 
510 	ReferenceParams		refParams		(TEXTURETYPE_CUBE);
511 	vector<float>		texCoord;
512 	tcu::Surface		renderedFrame	(viewportWidth, viewportHeight);
513 
514 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
515 	refParams.samplerType	= getSamplerType(vk::mapVkFormat(m_testParameters.format));
516 	refParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
517 	refParams.lodMode		= LODMODE_EXACT; // Use ideal lod.
518 
519 	// Compute grid.
520 	vector<IVec4> gridLayout;
521 	computeGridLayout(gridLayout, viewportWidth, viewportHeight);
522 
523 	// Bias values.
524 	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
525 
526 	// Projection values \note Less agressive than in 2D case due to smaller quads.
527 	static const Vec4 s_projections[] =
528 	{
529 		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
530 		Vec4(1.3f, 0.8f, 0.6f, 1.1f),
531 		Vec4(0.8f, 1.0f, 1.2f, 0.8f),
532 		Vec4(1.2f, 1.0f, 1.3f, 0.9f)
533 	};
534 
535 	// Render with GL
536 	for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
537 	{
538 		const float			curX		= (float)gridLayout[cellNdx].x();
539 		const float			curY		= (float)gridLayout[cellNdx].y();
540 		const float			curW		= (float)gridLayout[cellNdx].z();
541 		const float			curH		= (float)gridLayout[cellNdx].w();
542 		const tcu::CubeFace	cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
543 
544 		DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
545 		computeQuadTexCoordCube(texCoord, cubeFace);
546 
547 		if (isProjected)
548 		{
549 			refParams.flags	|= ReferenceParams::PROJECTED;
550 			refParams.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
551 		}
552 
553 		if (useLodBias)
554 		{
555 			refParams.flags	|= ReferenceParams::USE_BIAS;
556 			refParams.bias	 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
557 		}
558 
559 		// Render
560 		m_renderer.setViewport(curX, curY, curW, curH);
561 		m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
562 	}
563 
564 	// Render reference and compare
565 	{
566 		const tcu::IVec4		formatBitDepth		= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
567 		const tcu::PixelFormat	pixelFormat			(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
568 		tcu::Surface			referenceFrame		(viewportWidth, viewportHeight);
569 		tcu::Surface			errorMask			(viewportWidth, viewportHeight);
570 		int						numFailedPixels		= 0;
571 		tcu::LookupPrecision	lookupPrec;
572 		tcu::LodPrecision		lodPrec;
573 
574 		// Params for rendering reference
575 		refParams.sampler					= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
576 		refParams.sampler.seamlessCubeMap	= true;
577 		refParams.lodMode					= LODMODE_EXACT;
578 
579 		// Comparison parameters
580 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
581 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat)-2, tcu::IVec4(0)));
582 		lookupPrec.coordBits		= isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
583 		lookupPrec.uvwBits			= tcu::IVec3(5,5,0);
584 		lodPrec.derivateBits		= 10;
585 		lodPrec.lodBits				= isProjected ? 3 : 6;
586 
587 		for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
588 		{
589 			const int				curX		= gridLayout[cellNdx].x();
590 			const int				curY		= gridLayout[cellNdx].y();
591 			const int				curW		= gridLayout[cellNdx].z();
592 			const int				curH		= gridLayout[cellNdx].w();
593 			const tcu::CubeFace		cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
594 
595 			DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
596 			computeQuadTexCoordCube(texCoord, cubeFace);
597 
598 			if (isProjected)
599 			{
600 				refParams.flags	|= ReferenceParams::PROJECTED;
601 				refParams.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
602 			}
603 
604 			if (useLodBias)
605 			{
606 				refParams.flags	|= ReferenceParams::USE_BIAS;
607 				refParams.bias	 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
608 			}
609 
610 			// Render ideal reference.
611 			{
612 				tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
613 				sampleTexture(idealDst, m_texture->getTexture(), &texCoord[0], refParams);
614 			}
615 
616 			// Compare this cell
617 			numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
618 														tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
619 														tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
620 														m_texture->getTexture(), &texCoord[0], refParams,
621 														lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
622 		}
623 
624 		if (numFailedPixels > 0)
625 		{
626 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
627 		}
628 
629 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
630 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
631 
632 		if (numFailedPixels > 0)
633 		{
634 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
635 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
636 		}
637 
638 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
639 
640 		{
641 			const bool isOk = numFailedPixels == 0;
642 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
643 		}
644 	}
645 }
646 
647 // Texture3DMipmapTestInstance
648 class Texture3DMipmapTestInstance : public TestInstance
649 {
650 public:
651 	typedef Texture3DMipmapTestCaseParameters	ParameterType;
652 
653 									Texture3DMipmapTestInstance		(Context& context, const ParameterType& testParameters);
654 									~Texture3DMipmapTestInstance	(void);
655 
656 	virtual tcu::TestStatus			iterate							(void);
657 
658 private:
659 									Texture3DMipmapTestInstance		(const Texture3DMipmapTestInstance& other);
660 	Texture3DMipmapTestInstance&	operator=						(const Texture3DMipmapTestInstance& other);
661 
662 	const ParameterType				m_testParameters;
663 	TestTexture3DSp					m_texture;
664 	TextureRenderer					m_renderer;
665 };
666 
Texture3DMipmapTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)667 Texture3DMipmapTestInstance::Texture3DMipmapTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
668 	: TestInstance		(context)
669 	, m_testParameters	(testParameters)
670 	, m_renderer		(context, testParameters.sampleCount, testParameters.width*4, testParameters.height*4)
671 {
672 	TCU_CHECK_INTERNAL(!(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
673 
674 	const tcu::TextureFormat&	texFmt		= mapVkFormat(testParameters.format);
675 	tcu::TextureFormatInfo		fmtInfo		= tcu::getTextureFormatInfo(texFmt);
676 	const tcu::Vec4&			cScale		= fmtInfo.lookupScale;
677 	const tcu::Vec4&			cBias		= fmtInfo.lookupBias;
678 	const int					numLevels	= deLog2Floor32(de::max(de::max(testParameters.width, testParameters.height), testParameters.depth))+1;
679 
680 	m_texture = TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.depth));
681 
682 	// Fill texture with colored grid.
683 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
684 	{
685 		const deUint32	step	= 0xff / (numLevels-1);
686 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
687 		const deUint32	dec		= 0xff - inc;
688 		const deUint32	rgb		= (0xff << 16) | (dec << 8) | inc;
689 		const deUint32	color	= 0xff000000 | rgb;
690 
691 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec()*cScale + cBias);
692 	}
693 
694 	m_renderer.add3DTexture(m_texture);
695 }
696 
~Texture3DMipmapTestInstance(void)697 Texture3DMipmapTestInstance::~Texture3DMipmapTestInstance (void)
698 {
699 }
700 
getBasicTexCoord3D(std::vector<float> & dst,int cellNdx)701 static void getBasicTexCoord3D (std::vector<float>& dst, int cellNdx)
702 {
703 	static const struct
704 	{
705 		const float sScale;
706 		const float sBias;
707 		const float tScale;
708 		const float tBias;
709 		const float rScale;
710 		const float rBias;
711 	} s_params[] =
712 	{
713 	//		sScale	sBias	tScale	tBias	rScale	rBias
714 		{	 0.9f,	-0.1f,	 0.7f,	 0.3f,	 0.8f,	 0.9f	},
715 		{	 1.2f,	-0.1f,	 1.1f,	 0.3f,	 1.0f,	 0.9f	},
716 		{	 1.5f,	 0.7f,	 0.9f,	-0.3f,	 1.1f,	 0.1f	},
717 		{	 1.2f,	 0.7f,	-2.3f,	-0.3f,	 1.1f,	 0.2f	},
718 		{	 1.1f,	 0.8f,	-1.3f,	-0.3f,	 2.9f,	 0.9f	},
719 		{	 3.4f,	 0.8f,	 4.0f,	 0.0f,	-3.3f,	-1.0f	},
720 		{	-3.4f,	-0.1f,	-4.0f,	 0.0f,	-5.1f,	 1.0f	},
721 		{	-4.0f,	-0.1f,	 3.4f,	 0.1f,	 5.7f,	 0.0f	},
722 		{	-5.6f,	 0.0f,	 0.5f,	 1.2f,	 3.9f,	 4.0f	},
723 		{	 5.0f,	-2.0f,	 3.1f,	 1.2f,	 5.1f,	 0.2f	},
724 		{	 2.5f,	-2.0f,	 6.3f,	 3.0f,	 5.1f,	 0.2f	},
725 		{	-8.3f,	 0.0f,	 7.1f,	 3.0f,	 2.0f,	 0.2f	},
726 		{	 3.8f,	 0.0f,	 9.7f,	 1.0f,	 7.0f,	 0.7f	},
727 		{	13.3f,	 0.0f,	 7.1f,	 3.0f,	 2.0f,	 0.2f	},
728 		{	16.0f,	 8.0f,	12.7f,	 1.0f,	17.1f,	 0.7f	},
729 		{	15.3f,	 0.0f,	20.1f,	 3.0f,	33.0f,	 3.2f	}
730 	};
731 
732 	const float sScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sScale;
733 	const float sBias	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sBias;
734 	const float tScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tScale;
735 	const float tBias	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tBias;
736 	const float rScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rScale;
737 	const float rBias	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rBias;
738 
739 	dst.resize(3*4);
740 
741 	dst[0] = sBias;			dst[ 1] = tBias;			dst[ 2] = rBias;
742 	dst[3] = sBias;			dst[ 4] = tBias+tScale;		dst[ 5] = rBias+rScale*0.5f;
743 	dst[6] = sBias+sScale;	dst[ 7] = tBias;			dst[ 8] = rBias+rScale*0.5f;
744 	dst[9] = sBias+sScale;	dst[10] = tBias+tScale;		dst[11] = rBias+rScale;
745 }
746 
getAffineTexCoord3D(std::vector<float> & dst,int cellNdx)747 static void getAffineTexCoord3D (std::vector<float>& dst, int cellNdx)
748 {
749 	// Use basic coords as base.
750 	getBasicTexCoord3D(dst, cellNdx);
751 
752 	// Rotate based on cell index.
753 	const float		angleX		= 0.0f + 2.0f*DE_PI * ((float)cellNdx / 16.0f);
754 	const float		angleY		= 1.0f + 2.0f*DE_PI * ((float)cellNdx / 32.0f);
755 	const tcu::Mat3	rotMatrix	= tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);
756 
757 	const Vec3		p0			= rotMatrix * Vec3(dst[0], dst[ 1], dst[ 2]);
758 	const Vec3		p1			= rotMatrix * Vec3(dst[3], dst[ 4], dst[ 5]);
759 	const Vec3		p2			= rotMatrix * Vec3(dst[6], dst[ 7], dst[ 8]);
760 	const Vec3		p3			= rotMatrix * Vec3(dst[9], dst[10], dst[11]);
761 
762 	dst[0] = p0.x();	dst[ 1] = p0.y();	dst[ 2] = p0.z();
763 	dst[3] = p1.x();	dst[ 4] = p1.y();	dst[ 5] = p1.z();
764 	dst[6] = p2.x();	dst[ 7] = p2.y();	dst[ 8] = p2.z();
765 	dst[9] = p3.x();	dst[10] = p3.y();	dst[11] = p3.z();
766 }
767 
iterate(void)768 tcu::TestStatus Texture3DMipmapTestInstance::iterate (void)
769 {
770 	const tcu::TextureFormat&		texFmt			= m_texture->getTextureFormat();
771 	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
772 	const Sampler::FilterMode		magFilter		= Sampler::NEAREST;
773 	const int						viewportWidth	= m_renderer.getRenderWidth();
774 	const int						viewportHeight	= m_renderer.getRenderHeight();
775 
776 	const bool						isProjected		= m_testParameters.coordType == COORDTYPE_PROJECTED;
777 	const bool						useLodBias		= m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
778 
779 	// Viewport is divided into 4x4 grid.
780 	const int						gridWidth		= 4;
781 	const int						gridHeight		= 4;
782 	const int						cellWidth		= viewportWidth / gridWidth;
783 	const int						cellHeight		= viewportHeight / gridHeight;
784 
785 	ReferenceParams					refParams		(TEXTURETYPE_3D);
786 
787 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
788 	vector<float>					texCoord;
789 
790 	// Sampling parameters.
791 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
792 	refParams.samplerType	= getSamplerType(texFmt);
793 
794 	refParams.colorBias		= fmtInfo.lookupBias;
795 	refParams.colorScale	= fmtInfo.lookupScale;
796 	refParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
797 
798 	// Bias values.
799 	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
800 
801 	// Projection values.
802 	static const Vec4 s_projections[] =
803 	{
804 		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
805 		Vec4(1.3f, 0.8f, 0.6f, 2.0f),
806 		Vec4(0.8f, 1.0f, 1.7f, 0.6f),
807 		Vec4(1.2f, 1.0f, 1.7f, 1.5f)
808 	};
809 
810 	// Render cells.
811 	for (int gridY = 0; gridY < gridHeight; gridY++)
812 	{
813 		for (int gridX = 0; gridX < gridWidth; gridX++)
814 		{
815 			const int	curX		= cellWidth*gridX;
816 			const int	curY		= cellHeight*gridY;
817 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
818 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
819 			const int	cellNdx		= gridY*gridWidth + gridX;
820 
821 			// Compute texcoord.
822 			switch (m_testParameters.coordType)
823 			{
824 				case COORDTYPE_BASIC_BIAS:	// Fall-through.
825 				case COORDTYPE_PROJECTED:
826 				case COORDTYPE_BASIC:		getBasicTexCoord3D	(texCoord, cellNdx);	break;
827 				case COORDTYPE_AFFINE:		getAffineTexCoord3D	(texCoord, cellNdx);	break;
828 				default:					DE_ASSERT(DE_FALSE);
829 			}
830 
831 			// Set projection.
832 			if (isProjected)
833 				refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
834 
835 			// Set LOD bias.
836 			if (useLodBias)
837 				refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
838 
839 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
840 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
841 		}
842 	}
843 
844 	// Compare and log
845 	{
846 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
847 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
848 		const bool				isTrilinear		= m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
849 		tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
850 		tcu::Surface			errorMask		(viewportWidth, viewportHeight);
851 		tcu::LookupPrecision	lookupPrec;
852 		tcu::LodPrecision		lodPrec;
853 		int						numFailedPixels	= 0;
854 
855 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 20);
856 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
857 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
858 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
859 		lodPrec.derivateBits		= 10;
860 		lodPrec.lodBits				= isProjected ? 6 : 8;
861 
862 		for (int gridY = 0; gridY < gridHeight; gridY++)
863 		{
864 			for (int gridX = 0; gridX < gridWidth; gridX++)
865 			{
866 				const int	curX		= cellWidth*gridX;
867 				const int	curY		= cellHeight*gridY;
868 				const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
869 				const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
870 				const int	cellNdx		= gridY*gridWidth + gridX;
871 
872 				switch (m_testParameters.coordType)
873 				{
874 					case COORDTYPE_BASIC_BIAS:	// Fall-through.
875 					case COORDTYPE_PROJECTED:
876 					case COORDTYPE_BASIC:		getBasicTexCoord3D	(texCoord, cellNdx);	break;
877 					case COORDTYPE_AFFINE:		getAffineTexCoord3D	(texCoord, cellNdx);	break;
878 					default:					DE_ASSERT(DE_FALSE);
879 				}
880 
881 				if (isProjected)
882 					refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
883 
884 				if (useLodBias)
885 					refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
886 
887 				// Render ideal result
888 				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
889 							  m_texture->getTexture(), &texCoord[0], refParams);
890 
891 				// Compare this cell
892 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
893 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
894 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
895 															m_texture->getTexture(), &texCoord[0], refParams,
896 															lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
897 			}
898 		}
899 
900 		if (numFailedPixels > 0)
901 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
902 
903 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
904 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
905 
906 		if (numFailedPixels > 0)
907 		{
908 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
909 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
910 		}
911 
912 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
913 
914 		{
915 			const bool isOk = numFailedPixels == 0;
916 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
917 		}
918 	}
919 }
920 
921 // Texture2DLodControlTestInstance
922 class Texture2DLodControlTestInstance : public TestInstance
923 {
924 public:
925 	typedef Texture2DMipmapTestCaseParameters	ParameterType;
926 
927 										Texture2DLodControlTestInstance		(Context& context, const ParameterType& testParameters);
928 										~Texture2DLodControlTestInstance	(void);
929 
930 	virtual tcu::TestStatus				iterate								(void);
931 
932 protected:
933 	virtual void						getReferenceParams					(ReferenceParams& params, int cellNdx) = 0;
934 
935 	const int							m_texWidth;
936 	const int							m_texHeight;
937 
938 private:
939 										Texture2DLodControlTestInstance		(const Texture2DLodControlTestInstance& other);
940 	Texture2DLodControlTestInstance&	operator=							(const Texture2DLodControlTestInstance& other);
941 
942 	const ParameterType					m_testParameters;
943 	tcu::Sampler::FilterMode			m_minFilter;
944 	TestTexture2DSp						m_texture;
945 	TextureRenderer						m_renderer;
946 };
947 
Texture2DLodControlTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)948 Texture2DLodControlTestInstance::Texture2DLodControlTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
949 	: TestInstance		(context)
950 	, m_texWidth		(64) //64
951 	, m_texHeight		(64)//64
952 	, m_testParameters	(testParameters)
953 	, m_minFilter		(testParameters.minFilter)
954 	, m_texture			(DE_NULL)
955 	, m_renderer		(context, testParameters.sampleCount, m_texWidth*4, m_texHeight*4)
956 {
957 	const VkFormat	format		= VK_FORMAT_R8G8B8A8_UNORM;
958 	const int		numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
959 
960 	m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(format), m_texWidth, m_texHeight));
961 
962 	// Fill texture with colored grid.
963 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
964 	{
965 		const deUint32	step	= 0xff / (numLevels-1);
966 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
967 		const deUint32	dec		= 0xff - inc;
968 		const deUint32	rgb		= (inc << 16) | (dec << 8) | 0xff;
969 		const deUint32	color	= 0xff000000 | rgb;
970 
971 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
972 	}
973 
974 	m_renderer.add2DTexture(m_texture);
975 }
976 
~Texture2DLodControlTestInstance(void)977 Texture2DLodControlTestInstance::~Texture2DLodControlTestInstance (void)
978 {
979 }
980 
iterate(void)981 tcu::TestStatus Texture2DLodControlTestInstance::iterate (void)
982 {
983 	const tcu::Sampler::WrapMode	wrapS			= Sampler::REPEAT_GL;
984 	const tcu::Sampler::WrapMode	wrapT			= Sampler::REPEAT_GL;
985 	const tcu::Sampler::FilterMode	magFilter		= Sampler::NEAREST;
986 
987 	const tcu::Texture2D&			refTexture		= m_texture->getTexture();
988 
989 	const int						viewportWidth	= m_renderer.getRenderWidth();
990 	const int						viewportHeight	= m_renderer.getRenderHeight();
991 
992 	tcu::Sampler					sampler			= util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
993 
994 	ReferenceParams					refParams		(TEXTURETYPE_2D, sampler);
995 	vector<float>					texCoord;
996 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
997 
998 	// Viewport is divided into 4x4 grid.
999 	const int						gridWidth		= 4;
1000 	const int						gridHeight		= 4;
1001 	const int						cellWidth		= viewportWidth / gridWidth;
1002 	const int						cellHeight		= viewportHeight / gridHeight;
1003 
1004 	refParams.maxLevel = deLog2Floor32(de::max(m_texWidth, m_texHeight));
1005 
1006 	// Render cells.
1007 	for (int gridY = 0; gridY < gridHeight; gridY++)
1008 	{
1009 		for (int gridX = 0; gridX < gridWidth; gridX++)
1010 		{
1011 			const int	curX		= cellWidth*gridX;
1012 			const int	curY		= cellHeight*gridY;
1013 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1014 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1015 			const int	cellNdx		= gridY*gridWidth + gridX;
1016 
1017 			// Compute texcoord.
1018 			getBasicTexCoord2D(texCoord, cellNdx);
1019 			// Render
1020 			getReferenceParams(refParams,cellNdx);
1021 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1022 			m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel);
1023 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1024 		}
1025 	}
1026 
1027 	// Compare and log.
1028 	{
1029 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1030 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1031 		const bool				isTrilinear		= m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1032 		tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
1033 		tcu::Surface			errorMask		(viewportWidth, viewportHeight);
1034 		tcu::LookupPrecision	lookupPrec;
1035 		tcu::LodPrecision		lodPrec;
1036 		int						numFailedPixels	= 0;
1037 
1038 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
1039 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
1040 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1041 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
1042 		lodPrec.derivateBits		= 10;
1043 		lodPrec.lodBits				= 8;
1044 
1045 		for (int gridY = 0; gridY < gridHeight; gridY++)
1046 		{
1047 			for (int gridX = 0; gridX < gridWidth; gridX++)
1048 			{
1049 				const int	curX		= cellWidth*gridX;
1050 				const int	curY		= cellHeight*gridY;
1051 				const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1052 				const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1053 				const int	cellNdx		= gridY*gridWidth + gridX;
1054 
1055 				getBasicTexCoord2D(texCoord, cellNdx);
1056 				getReferenceParams(refParams, cellNdx);
1057 
1058 				// Render ideal result
1059 				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
1060 							  refTexture, &texCoord[0], refParams);
1061 
1062 				// Compare this cell
1063 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1064 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1065 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1066 															m_texture->getTexture(), &texCoord[0], refParams,
1067 															lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1068 			}
1069 		}
1070 
1071 		if (numFailedPixels > 0)
1072 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1073 
1074 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1075 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
1076 
1077 		if (numFailedPixels > 0)
1078 		{
1079 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1080 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
1081 		}
1082 
1083 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
1084 
1085 		{
1086 			const bool isOk = numFailedPixels == 0;
1087 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1088 		}
1089 	}
1090 }
1091 
1092 class Texture2DMinLodTestInstance : public Texture2DLodControlTestInstance
1093 {
1094 public:
Texture2DMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1095 	Texture2DMinLodTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1096 		: Texture2DLodControlTestInstance(context, testParameters)
1097 	{
1098 	}
1099 
1100 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1101 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1102 	{
1103 		params.minLod = getMinLodForCell(cellNdx);
1104 	}
1105 };
1106 
1107 class Texture2DMaxLodTestInstance : public Texture2DLodControlTestInstance
1108 {
1109 public:
Texture2DMaxLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1110 	Texture2DMaxLodTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1111 		: Texture2DLodControlTestInstance(context, testParameters)
1112 	{
1113 	}
1114 
1115 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1116 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1117 	{
1118 		params.maxLod = getMaxLodForCell(cellNdx);
1119 	}
1120 };
1121 
1122 class Texture2DBaseLevelTestInstance : public Texture2DLodControlTestInstance
1123 {
1124 public:
Texture2DBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1125 	Texture2DBaseLevelTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1126 		: Texture2DLodControlTestInstance(context, testParameters)
1127 		, m_testParam (testParameters)
1128 	{
1129 	}
1130 
1131 protected:
1132 	const Texture2DMipmapTestCaseParameters m_testParam;
1133 
getBaseLevel(int cellNdx) const1134 	int getBaseLevel (int cellNdx) const
1135 	{
1136 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1137 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1138 
1139 		return baseLevel;
1140 	}
1141 
getReferenceParams(ReferenceParams & params,int cellNdx)1142 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1143 	{
1144 		params.baseLevel = getBaseLevel(cellNdx);
1145 	}
1146 };
1147 
1148 class Texture2DMaxLevelTestInstance : public Texture2DLodControlTestInstance
1149 {
1150 public:
Texture2DMaxLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1151 	Texture2DMaxLevelTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1152 		: Texture2DLodControlTestInstance(context, testParameters)
1153 		, m_testParam (testParameters)
1154 	{
1155 	}
1156 
1157 protected:
1158 	const Texture2DMipmapTestCaseParameters m_testParam;
1159 
getMaxLevel(int cellNdx) const1160 	int getMaxLevel (int cellNdx) const
1161 	{
1162 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1163 		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x82cfa4e) % numLevels;
1164 
1165 		return maxLevel;
1166 	}
1167 
getReferenceParams(ReferenceParams & params,int cellNdx)1168 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1169 	{
1170 		params.maxLevel = getMaxLevel(cellNdx);
1171 	}
1172 };
1173 
1174 // TextureCubeLodControlTestInstance
1175 class TextureCubeLodControlTestInstance : public TestInstance
1176 {
1177 public:
1178 	typedef TextureCubeMipmapTestCaseParameters	ParameterType;
1179 
1180 										TextureCubeLodControlTestInstance	(Context& context, const ParameterType& testParameters);
1181 										~TextureCubeLodControlTestInstance	(void);
1182 
1183 	virtual tcu::TestStatus				iterate								(void);
1184 
1185 protected:
1186 	virtual void						getReferenceParams					(ReferenceParams& params, int cellNdx)	= DE_NULL;
1187 
1188 	const int							m_texSize;
1189 
1190 private:
1191 										TextureCubeLodControlTestInstance	(const TextureCubeLodControlTestInstance& other);
1192 	TextureCubeLodControlTestInstance&	operator=							(const TextureCubeLodControlTestInstance& other);
1193 
1194 	const ParameterType					m_testParameters;
1195 	tcu::Sampler::FilterMode			m_minFilter;
1196 	TestTextureCubeSp					m_texture;
1197 	TextureRenderer						m_renderer;
1198 };
1199 
TextureCubeLodControlTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1200 TextureCubeLodControlTestInstance::TextureCubeLodControlTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1201 	: TestInstance		(context)
1202 	, m_texSize			(64)
1203 	, m_testParameters	(testParameters)
1204 	, m_minFilter		(testParameters.minFilter)
1205 	, m_texture			(DE_NULL)
1206 	, m_renderer		(context, testParameters.sampleCount, m_texSize*2, m_texSize*2)
1207 {
1208 	const VkFormat	format		= VK_FORMAT_R8G8B8A8_UNORM;
1209 	const int		numLevels	= deLog2Floor32(m_texSize)+1;
1210 
1211 	m_texture = TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(format), m_texSize));
1212 
1213 	// Fill texture with colored grid.
1214 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1215 	{
1216 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1217 		{
1218 			const deUint32	step	= 0xff / (numLevels-1);
1219 			const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
1220 			const deUint32	dec		= 0xff - inc;
1221 			deUint32		rgb		= 0;
1222 
1223 			switch (faceNdx)
1224 			{
1225 				case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
1226 				case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
1227 				case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
1228 				case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
1229 				case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
1230 				case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
1231 			}
1232 
1233 			const deUint32	color	= 0xff000000 | rgb;
1234 
1235 			tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
1236 		}
1237 	}
1238 
1239 	m_renderer.addCubeTexture(m_texture);
1240 }
1241 
~TextureCubeLodControlTestInstance(void)1242 TextureCubeLodControlTestInstance::~TextureCubeLodControlTestInstance (void)
1243 {
1244 }
1245 
iterate(void)1246 tcu::TestStatus TextureCubeLodControlTestInstance::iterate (void)
1247 {
1248 	const tcu::Sampler::WrapMode	wrapS			= Sampler::CLAMP_TO_EDGE;
1249 	const tcu::Sampler::WrapMode	wrapT			= Sampler::CLAMP_TO_EDGE;
1250 	const tcu::Sampler::FilterMode	magFilter		= Sampler::NEAREST;
1251 
1252 	const tcu::TextureCube&			refTexture		= m_texture->getTexture();
1253 	const int						viewportWidth	= m_renderer.getRenderWidth();
1254 	const int						viewportHeight	= m_renderer.getRenderHeight();
1255 
1256 	tcu::Sampler					sampler			= util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1257 	ReferenceParams					refParams		(TEXTURETYPE_CUBE, sampler);
1258 	vector<float>					texCoord;
1259 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
1260 
1261 	refParams.maxLevel = deLog2Floor32(m_texSize);
1262 
1263 	// Compute grid.
1264 	vector<tcu::IVec4> gridLayout;
1265 	computeGridLayout(gridLayout, viewportWidth, viewportHeight);
1266 
1267 	for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1268 	{
1269 		const int			curX		= gridLayout[cellNdx].x();
1270 		const int			curY		= gridLayout[cellNdx].y();
1271 		const int			curW		= gridLayout[cellNdx].z();
1272 		const int			curH		= gridLayout[cellNdx].w();
1273 		const tcu::CubeFace	cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1274 
1275 		computeQuadTexCoordCube(texCoord, cubeFace);
1276 		getReferenceParams(refParams, cellNdx);
1277 
1278 		// Render with GL.
1279 		m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1280 		m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel);
1281 		m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1282 	}
1283 
1284 	// Render reference and compare
1285 	{
1286 		const tcu::IVec4		formatBitDepth		= getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1287 		const tcu::PixelFormat	pixelFormat			(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1288 		tcu::Surface			referenceFrame		(viewportWidth, viewportHeight);
1289 		tcu::Surface			errorMask			(viewportWidth, viewportHeight);
1290 		int						numFailedPixels		= 0;
1291 		tcu::LookupPrecision	lookupPrec;
1292 		tcu::LodPrecision		lodPrec;
1293 
1294 		// Params for rendering reference
1295 		refParams.sampler					= util::createSampler(wrapS, wrapT, m_testParameters.minFilter, magFilter);
1296 		refParams.sampler.seamlessCubeMap	= true;
1297 		refParams.lodMode					= LODMODE_EXACT;
1298 
1299 		// Comparison parameters
1300 		lookupPrec.colorMask				= getCompareMask(pixelFormat);
1301 		lookupPrec.colorThreshold			= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat)-2, IVec4(0)));
1302 		lookupPrec.coordBits				= tcu::IVec3(10);
1303 		lookupPrec.uvwBits					= tcu::IVec3(5,5,0);
1304 		lodPrec.derivateBits				= 10;
1305 		lodPrec.lodBits						= 6;
1306 
1307 		for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1308 		{
1309 			const int				curX		= gridLayout[cellNdx].x();
1310 			const int				curY		= gridLayout[cellNdx].y();
1311 			const int				curW		= gridLayout[cellNdx].z();
1312 			const int				curH		= gridLayout[cellNdx].w();
1313 			const tcu::CubeFace		cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1314 
1315 			computeQuadTexCoordCube(texCoord, cubeFace);
1316 			getReferenceParams(refParams, cellNdx);
1317 
1318 			// Render ideal reference.
1319 			{
1320 				tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
1321 				sampleTexture(idealDst, refTexture, &texCoord[0], refParams);
1322 			}
1323 
1324 			// Compare this cell
1325 			numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1326 														tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1327 														tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1328 														m_texture->getTexture(), &texCoord[0], refParams,
1329 														lookupPrec, lodPrec,  m_context.getTestContext().getWatchDog());
1330 		}
1331 
1332 		if (numFailedPixels > 0)
1333 			 m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1334 
1335 		 m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1336 											 << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1337 
1338 		if (numFailedPixels > 0)
1339 		{
1340 			 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1341 												 << TestLog::Image("ErrorMask", "Error mask", errorMask);
1342 		}
1343 
1344 		 m_context.getTestContext().getLog() << TestLog::EndImageSet;
1345 
1346 		{
1347 			const bool isOk = numFailedPixels == 0;
1348 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1349 		}
1350 	}
1351 }
1352 
1353 class TextureCubeMinLodTestInstance : public TextureCubeLodControlTestInstance
1354 {
1355 public:
TextureCubeMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1356 	TextureCubeMinLodTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1357 		: TextureCubeLodControlTestInstance(context, testParameters)
1358 	{
1359 	}
1360 
1361 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1362 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1363 	{
1364 		params.minLod = getMinLodForCell(cellNdx);
1365 	}
1366 };
1367 
1368 class TextureCubeMaxLodTestInstance : public TextureCubeLodControlTestInstance
1369 {
1370 public:
TextureCubeMaxLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1371 	TextureCubeMaxLodTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1372 		: TextureCubeLodControlTestInstance(context, testParameters)
1373 	{
1374 	}
1375 
1376 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1377 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1378 	{
1379 		params.maxLod = getMaxLodForCell(cellNdx);
1380 	}
1381 };
1382 
1383 class TextureCubeBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1384 {
1385 public:
TextureCubeBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1386 	TextureCubeBaseLevelTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1387 		: TextureCubeLodControlTestInstance(context, testParameters)
1388 		, m_testParam (testParameters)
1389 	{
1390 	}
1391 
1392 protected:
1393 	const TextureCubeMipmapTestCaseParameters m_testParam;
1394 
getBaseLevel(int cellNdx) const1395 	int getBaseLevel (int cellNdx) const
1396 	{
1397 		const int	numLevels	= deLog2Floor32(m_texSize)+1;
1398 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1399 
1400 		return baseLevel;
1401 	}
1402 
getReferenceParams(ReferenceParams & params,int cellNdx)1403 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1404 	{
1405 		params.baseLevel = getBaseLevel(cellNdx);
1406 	}
1407 };
1408 
1409 class TextureCubeMaxLevelTestInstance : public TextureCubeLodControlTestInstance
1410 {
1411 public:
TextureCubeMaxLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1412 	TextureCubeMaxLevelTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1413 		: TextureCubeLodControlTestInstance(context, testParameters)
1414 		, m_testParam (testParameters)
1415 	{
1416 	}
1417 
1418 protected:
1419 	const TextureCubeMipmapTestCaseParameters m_testParam;
getMaxLevel(int cellNdx) const1420 	int getMaxLevel (int cellNdx) const
1421 	{
1422 		const int	numLevels	= deLog2Floor32(m_texSize)+1;
1423 		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x974e21) % numLevels;
1424 
1425 		return maxLevel;
1426 	}
1427 
getReferenceParams(ReferenceParams & params,int cellNdx)1428 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1429 	{
1430 		params.maxLevel = getMaxLevel(cellNdx);
1431 	}
1432 };
1433 
1434 // Texture3DLodControlTestInstance
1435 class Texture3DLodControlTestInstance : public TestInstance
1436 {
1437 public:
1438 	typedef Texture3DMipmapTestCaseParameters	ParameterType;
1439 
1440 										Texture3DLodControlTestInstance		(Context& context, const ParameterType& testParameters);
1441 										~Texture3DLodControlTestInstance	(void);
1442 
1443 	virtual tcu::TestStatus				iterate								(void);
1444 
1445 protected:
1446 	virtual void						getReferenceParams					(ReferenceParams& params, int cellNdx)	= DE_NULL;
1447 
1448 	const int							m_texWidth;
1449 	const int							m_texHeight;
1450 	const int							m_texDepth;
1451 
1452 private:
1453 										Texture3DLodControlTestInstance		(const Texture3DLodControlTestInstance& other);
1454 	Texture3DLodControlTestInstance&	operator=							(const Texture3DLodControlTestInstance& other);
1455 
1456 	const ParameterType					m_testParameters;
1457 	tcu::Sampler::FilterMode			m_minFilter;
1458 	TestTexture3DSp						m_texture;
1459 	TextureRenderer						m_renderer;
1460 };
1461 
Texture3DLodControlTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1462 Texture3DLodControlTestInstance::Texture3DLodControlTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1463 	: TestInstance		(context)
1464 	, m_texWidth		(32)
1465 	, m_texHeight		(32)
1466 	, m_texDepth		(32)
1467 	, m_testParameters	(testParameters)
1468 	, m_minFilter		(testParameters.minFilter)
1469 	, m_texture			(DE_NULL)
1470 	, m_renderer		(context, testParameters.sampleCount, m_texWidth*4, m_texHeight*4)
1471 {
1472 	const VkFormat			format		= VK_FORMAT_R8G8B8A8_UNORM;
1473 	tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(mapVkFormat(format));
1474 	const tcu::Vec4&		cScale		= fmtInfo.lookupScale;
1475 	const tcu::Vec4&		cBias		= fmtInfo.lookupBias;
1476 	const int				numLevels	= deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth))+1;
1477 
1478 	m_texture = TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(format), m_texWidth, m_texHeight, m_texDepth));
1479 
1480 	// Fill texture with colored grid.
1481 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1482 	{
1483 		const deUint32	step	= 0xff / (numLevels-1);
1484 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
1485 		const deUint32	dec		= 0xff - inc;
1486 		const deUint32	rgb		= (inc << 16) | (dec << 8) | 0xff;
1487 		const deUint32	color	= 0xff000000 | rgb;
1488 
1489 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec()*cScale + cBias);
1490 	}
1491 
1492 	m_renderer.add3DTexture(m_texture);
1493 }
1494 
~Texture3DLodControlTestInstance(void)1495 Texture3DLodControlTestInstance::~Texture3DLodControlTestInstance (void)
1496 {
1497 }
1498 
iterate(void)1499 tcu::TestStatus Texture3DLodControlTestInstance::iterate (void)
1500 {
1501 	const tcu::Sampler::WrapMode	wrapS			= Sampler::CLAMP_TO_EDGE;
1502 	const tcu::Sampler::WrapMode	wrapT			= Sampler::CLAMP_TO_EDGE;
1503 	const tcu::Sampler::WrapMode	wrapR			= Sampler::CLAMP_TO_EDGE;
1504 	const tcu::Sampler::FilterMode	magFilter		= Sampler::NEAREST;
1505 
1506 	const tcu::Texture3D&			refTexture		= m_texture->getTexture();
1507 	const tcu::TextureFormat&		texFmt			= refTexture.getFormat();
1508 	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
1509 	const int						viewportWidth	= m_renderer.getRenderWidth();
1510 	const int						viewportHeight	= m_renderer.getRenderHeight();
1511 
1512 	tcu::Sampler					sampler			= util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1513 	ReferenceParams					refParams		(TEXTURETYPE_3D, sampler);
1514 	vector<float>					texCoord;
1515 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
1516 
1517 	// Viewport is divided into 4x4 grid.
1518 	const int						gridWidth		= 4;
1519 	const int						gridHeight		= 4;
1520 	const int						cellWidth		= viewportWidth / gridWidth;
1521 	const int						cellHeight		= viewportHeight / gridHeight;
1522 
1523 	// Sampling parameters.
1524 	refParams.sampler		= util::createSampler(wrapS, wrapT, wrapR, m_testParameters.minFilter, magFilter);
1525 	refParams.samplerType	= getSamplerType(texFmt);
1526 	refParams.colorBias		= fmtInfo.lookupBias;
1527 	refParams.colorScale	= fmtInfo.lookupScale;
1528 	refParams.maxLevel		= deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth));
1529 
1530 	// Render cells.
1531 	for (int gridY = 0; gridY < gridHeight; gridY++)
1532 	{
1533 		for (int gridX = 0; gridX < gridWidth; gridX++)
1534 		{
1535 			const int	curX		= cellWidth*gridX;
1536 			const int	curY		= cellHeight*gridY;
1537 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1538 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1539 			const int	cellNdx		= gridY*gridWidth + gridX;
1540 
1541 			// Compute texcoord.
1542 			getBasicTexCoord3D(texCoord, cellNdx);
1543 
1544 			getReferenceParams(refParams,cellNdx);
1545 			//Render
1546 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1547 			m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel);
1548 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1549 		}
1550 	}
1551 
1552 	// Compare and log
1553 	{
1554 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1555 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1556 		const bool				isTrilinear		= m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1557 		tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
1558 		tcu::Surface			errorMask		(viewportWidth, viewportHeight);
1559 		tcu::LookupPrecision	lookupPrec;
1560 		tcu::LodPrecision		lodPrec;
1561 		int						numFailedPixels	= 0;
1562 
1563 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 20);
1564 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
1565 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1566 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
1567 		lodPrec.derivateBits		= 10;
1568 		lodPrec.lodBits				= 8;
1569 
1570 		for (int gridY = 0; gridY < gridHeight; gridY++)
1571 		{
1572 			for (int gridX = 0; gridX < gridWidth; gridX++)
1573 			{
1574 				const int	curX		= cellWidth*gridX;
1575 				const int	curY		= cellHeight*gridY;
1576 				const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1577 				const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1578 				const int	cellNdx		= gridY*gridWidth + gridX;
1579 
1580 				getBasicTexCoord3D(texCoord, cellNdx);
1581 				getReferenceParams(refParams, cellNdx);
1582 
1583 				// Render ideal result
1584 				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
1585 							  refTexture, &texCoord[0], refParams);
1586 
1587 				// Compare this cell
1588 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1589 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1590 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1591 															m_texture->getTexture(), &texCoord[0], refParams,
1592 															lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1593 			}
1594 		}
1595 
1596 		if (numFailedPixels > 0)
1597 		{
1598 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1599 		}
1600 
1601 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1602 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
1603 
1604 		if (numFailedPixels > 0)
1605 		{
1606 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1607 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
1608 		}
1609 
1610 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
1611 
1612 		{
1613 			const bool isOk = numFailedPixels == 0;
1614 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1615 		}
1616 	}
1617 }
1618 
1619 class Texture3DMinLodTestInstance : public Texture3DLodControlTestInstance
1620 {
1621 public:
Texture3DMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1622 	Texture3DMinLodTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1623 		: Texture3DLodControlTestInstance(context, testParameters)
1624 	{
1625 	}
1626 
1627 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1628 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1629 	{
1630 		params.minLod = getMinLodForCell(cellNdx);
1631 	}
1632 };
1633 
1634 class Texture3DMaxLodTestInstance : public Texture3DLodControlTestInstance
1635 {
1636 public:
Texture3DMaxLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1637 	Texture3DMaxLodTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1638 		: Texture3DLodControlTestInstance(context, testParameters)
1639 	{
1640 	}
1641 
1642 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1643 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1644 	{
1645 		params.maxLod = getMaxLodForCell(cellNdx);
1646 	}
1647 };
1648 
1649 class Texture3DBaseLevelTestInstance : public Texture3DLodControlTestInstance
1650 {
1651 public:
Texture3DBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1652 	Texture3DBaseLevelTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1653 		: Texture3DLodControlTestInstance(context, testParameters)
1654 		,m_testParam (testParameters)
1655 	{
1656 	}
1657 
1658 protected:
1659 	const Texture3DMipmapTestCaseParameters m_testParam;
1660 
getBaseLevel(int cellNdx) const1661 	int getBaseLevel (int cellNdx) const
1662 	{
1663 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
1664 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1665 
1666 		return baseLevel;
1667 	}
1668 
getReferenceParams(ReferenceParams & params,int cellNdx)1669 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1670 	{
1671 		params.baseLevel = getBaseLevel(cellNdx);
1672 	}
1673 };
1674 
1675 class Texture3DMaxLevelTestInstance : public Texture3DLodControlTestInstance
1676 {
1677 public:
Texture3DMaxLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1678 	Texture3DMaxLevelTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1679 		: Texture3DLodControlTestInstance(context, testParameters)
1680 		,m_testParam (testParameters)
1681 	{
1682 	}
1683 
1684 protected:
1685 	const Texture3DMipmapTestCaseParameters m_testParam;
1686 
getMaxLevel(int cellNdx) const1687 	int getMaxLevel (int cellNdx) const
1688 	{
1689 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
1690 		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x9111e7) % numLevels;
1691 
1692 		return maxLevel;
1693 	}
1694 
getReferenceParams(ReferenceParams & params,int cellNdx)1695 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1696 	{
1697 		params.maxLevel = getMaxLevel(cellNdx);
1698 	}
1699 };
1700 
populateTextureMipmappingTests(tcu::TestCaseGroup * textureMipmappingTests)1701 void populateTextureMipmappingTests (tcu::TestCaseGroup* textureMipmappingTests)
1702 {
1703 	tcu::TestContext&	testCtx		= textureMipmappingTests->getTestContext();
1704 
1705 	static const struct
1706 	{
1707 		const char*				name;
1708 		const Sampler::WrapMode	mode;
1709 	} wrapModes[] =
1710 	{
1711 		{ "clamp",		Sampler::CLAMP_TO_EDGE		},
1712 		{ "repeat",		Sampler::REPEAT_GL			},
1713 		{ "mirror",		Sampler::MIRRORED_REPEAT_GL	}
1714 	};
1715 
1716 	static const struct
1717 	{
1718 		const char*					name;
1719 		const Sampler::FilterMode	mode;
1720 	} minFilterModes[] =
1721 	{
1722 		{ "nearest_nearest",	Sampler::NEAREST_MIPMAP_NEAREST	},
1723 		{ "linear_nearest",		Sampler::LINEAR_MIPMAP_NEAREST	},
1724 		{ "nearest_linear",		Sampler::NEAREST_MIPMAP_LINEAR	},
1725 		{ "linear_linear",		Sampler::LINEAR_MIPMAP_LINEAR	}
1726 	};
1727 
1728 	static const struct
1729 	{
1730 		const char*					name;
1731 		const Sampler::FilterMode	mode;
1732 	} magFilterModes[] =
1733 	{
1734 		{ "nearest",	Sampler::NEAREST},
1735 		{ "linear",		Sampler::LINEAR}
1736 	};
1737 
1738 
1739 	static const struct
1740 	{
1741 		const CoordType		type;
1742 		const char*			name;
1743 		const char*			desc;
1744 	} coordTypes[] =
1745 	{
1746 		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
1747 		{ COORDTYPE_AFFINE,		"affine",		"Mipmapping with affine coordinate transform"		},
1748 		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			}
1749 	};
1750 
1751 	static const struct
1752 	{
1753 		const char*		name;
1754 		const int		width;
1755 		const int		height;
1756 	} tex2DSizes[] =
1757 	{
1758 		{ DE_NULL,		64, 64 }, // Default.
1759 		{ "npot",		63, 57 },
1760 		{ "non_square",	32, 64 }
1761 	};
1762 
1763 	static const struct
1764 	{
1765 		const char*		name;
1766 		const int		width;
1767 		const int		height;
1768 		const int		depth;
1769 	} tex3DSizes[] =
1770 	{
1771 		{ DE_NULL,		32, 32, 32 }, // Default.
1772 		{ "npot",		33, 29, 27 }
1773 	};
1774 
1775 	const int cubeMapSize = 64;
1776 
1777 	static const struct
1778 	{
1779 		const CoordType		type;
1780 		const char*			name;
1781 		const char*			desc;
1782 	} cubeCoordTypes[] =
1783 	{
1784 		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
1785 		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			},
1786 		{ COORDTYPE_BASIC_BIAS,	"bias",			"User-supplied bias value"							}
1787 	};
1788 
1789 	// 2D cases.
1790 	{
1791 		de::MovePtr<tcu::TestCaseGroup>	group2D				(new tcu::TestCaseGroup(testCtx, "2d", "2D Mipmap Filtering"));
1792 
1793 		de::MovePtr<tcu::TestCaseGroup>	biasGroup2D			(new tcu::TestCaseGroup(testCtx, "bias", "User-supplied bias value"));
1794 		de::MovePtr<tcu::TestCaseGroup>	minLodGroup2D		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
1795 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroup2D		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
1796 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroup2D	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
1797 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroup2D		(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
1798 
1799 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
1800 		{
1801 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup		(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name, coordTypes[coordType].desc));
1802 
1803 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1804 			{
1805 				for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
1806 				{
1807 					// Add non_square variants to basic cases only.
1808 					int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
1809 
1810 					for (int size = 0; size < sizeEnd; size++)
1811 					{
1812 						Texture2DMipmapTestCaseParameters	testParameters;
1813 
1814 						testParameters.coordType	= coordTypes[coordType].type;
1815 						testParameters.minFilter	= minFilterModes[minFilter].mode;
1816 						testParameters.wrapS		= wrapModes[wrapMode].mode;
1817 						testParameters.wrapT		= wrapModes[wrapMode].mode;
1818 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM; //not sure (GL_RGBA)
1819 						testParameters.width		= tex2DSizes[size].width;
1820 						testParameters.height		= tex2DSizes[size].height;
1821 						testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1822 
1823 						std::ostringstream name;
1824 						name << minFilterModes[minFilter].name
1825 							 << "_" << wrapModes[wrapMode].name;
1826 
1827 						if (tex2DSizes[size].name)
1828 							name << "_" << tex2DSizes[size].name;
1829 
1830 						coordTypeGroup->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
1831 					}
1832 				}
1833 			}
1834 
1835 			group2D->addChild(coordTypeGroup.release());
1836 		}
1837 
1838 		// 2D bias variants.
1839 		{
1840 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1841 			{
1842 				Texture2DMipmapTestCaseParameters	testParameters;
1843 
1844 				testParameters.coordType	= COORDTYPE_BASIC_BIAS;
1845 				testParameters.minFilter	= minFilterModes[minFilter].mode;
1846 				testParameters.magFilter	= minFilterModes[minFilter].mode;
1847 				testParameters.wrapS		= Sampler::REPEAT_GL;
1848 				testParameters.wrapT		= Sampler::REPEAT_GL;
1849 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM; //not sure (GL_RGBA)
1850 				testParameters.width		= tex2DSizes[0].width;
1851 				testParameters.height		= tex2DSizes[0].height;
1852 				testParameters.programs.push_back(PROGRAM_2D_FLOAT_BIAS);
1853 
1854 				std::ostringstream name;
1855 				name << minFilterModes[minFilter].name;
1856 
1857 				biasGroup2D->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
1858 			}
1859 		}
1860 
1861 		// 2D LOD controls.
1862 		{
1863 			// MIN_LOD
1864 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1865 			{
1866 				Texture2DMipmapTestCaseParameters	testParameters;
1867 				testParameters.minFilter	= minFilterModes[minFilter].mode;
1868 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1869 
1870 				minLodGroup2D->addChild(new TextureTestCase<Texture2DMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1871 			}
1872 
1873 			// MAX_LOD
1874 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1875 			{
1876 				Texture2DMipmapTestCaseParameters	testParameters;
1877 				testParameters.minFilter = minFilterModes[minFilter].mode;
1878 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1879 
1880 				maxLodGroup2D->addChild(new TextureTestCase<Texture2DMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1881 			}
1882 		}
1883 
1884 		{
1885 			// BASE_LEVEL
1886 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1887 			{
1888 				Texture2DMipmapTestCaseParameters	testParameters;
1889 				testParameters.minFilter = minFilterModes[minFilter].mode;
1890 				testParameters.minFilterName = minFilterModes[minFilter].name;
1891 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1892 
1893 				baseLevelGroup2D->addChild(new TextureTestCase<Texture2DBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1894 			}
1895 
1896 			// MAX_LEVEL
1897 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1898 			{
1899 				Texture2DMipmapTestCaseParameters	testParameters;
1900 				testParameters.minFilter = minFilterModes[minFilter].mode;
1901 				testParameters.minFilterName = minFilterModes[minFilter].name;
1902 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1903 
1904 				maxLevelGroup2D->addChild(new TextureTestCase<Texture2DMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1905 			}
1906 		}
1907 
1908 		group2D->addChild(biasGroup2D.release());
1909 		group2D->addChild(minLodGroup2D.release());
1910 		group2D->addChild(maxLodGroup2D.release());
1911 		group2D->addChild(baseLevelGroup2D.release());
1912 		group2D->addChild(maxLevelGroup2D.release());
1913 
1914 		textureMipmappingTests->addChild(group2D.release());
1915 	}
1916 
1917 	// Cubemap cases.
1918 	{
1919 		de::MovePtr<tcu::TestCaseGroup>	groupCube			(new tcu::TestCaseGroup(testCtx, "cubemap", "Cube Mipmap Filtering"));
1920 
1921 		de::MovePtr<tcu::TestCaseGroup>	minLodGroupCube		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
1922 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroupCube		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
1923 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
1924 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
1925 
1926 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
1927 		{
1928 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup	(new tcu::TestCaseGroup(testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc));
1929 
1930 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1931 			{
1932 				for (int magFilter = 0; magFilter < DE_LENGTH_OF_ARRAY(magFilterModes); magFilter++)
1933 				{
1934 					for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
1935 					{
1936 						TextureCubeMipmapTestCaseParameters	testParameters;
1937 
1938 						testParameters.coordType		= cubeCoordTypes[coordType].type;
1939 						testParameters.minFilter		= minFilterModes[minFilter].mode;
1940 						testParameters.magFilter		= magFilterModes[magFilter].mode;
1941 						testParameters.minFilterName	= minFilterModes[minFilter].name;
1942 						testParameters.wrapS			= wrapModes[wrapMode].mode;
1943 						testParameters.wrapT			= wrapModes[wrapMode].mode;
1944 						testParameters.format			= VK_FORMAT_R8G8B8A8_UNORM;
1945 						testParameters.size				= cubeMapSize;
1946 						testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1947 						testParameters.programs.push_back(PROGRAM_CUBE_FLOAT_BIAS);
1948 
1949 						std::ostringstream name;
1950 						name << minFilterModes[minFilter].name
1951 							 << "_" << magFilterModes[magFilter].name
1952 							 << "_" << wrapModes[wrapMode].name;
1953 
1954 						coordTypeGroup->addChild(new TextureTestCase<TextureCubeMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
1955 					}
1956 				}
1957 			}
1958 
1959 			groupCube->addChild(coordTypeGroup.release());
1960 		}
1961 
1962 		// Cubemap LOD controls.
1963 		{
1964 			// MIN_LOD
1965 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1966 			{
1967 				TextureCubeMipmapTestCaseParameters	testParameters;
1968 				testParameters.minFilter	= minFilterModes[minFilter].mode;
1969 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1970 
1971 				minLodGroupCube->addChild(new TextureTestCase<TextureCubeMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1972 			}
1973 
1974 			// MAX_LOD
1975 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1976 			{
1977 				TextureCubeMipmapTestCaseParameters	testParameters;
1978 				testParameters.minFilter	= minFilterModes[minFilter].mode;
1979 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1980 
1981 				maxLodGroupCube->addChild(new TextureTestCase<TextureCubeMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1982 			}
1983 		}
1984 
1985 		{
1986 			// BASE_LEVEL
1987 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1988 			{
1989 				TextureCubeMipmapTestCaseParameters	testParameters;
1990 				testParameters.minFilter = minFilterModes[minFilter].mode;
1991 				testParameters.minFilterName = minFilterModes[minFilter].name;
1992 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1993 
1994 				baseLevelGroupCube->addChild(new TextureTestCase<TextureCubeBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
1995 			}
1996 
1997 			// MAX_LEVEL
1998 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1999 			{
2000 				TextureCubeMipmapTestCaseParameters	testParameters;
2001 				testParameters.minFilter = minFilterModes[minFilter].mode;
2002 				testParameters.minFilterName = minFilterModes[minFilter].name;
2003 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
2004 
2005 				maxLevelGroupCube->addChild(new TextureTestCase<TextureCubeMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
2006 			}
2007 		}
2008 
2009 		groupCube->addChild(minLodGroupCube.release());
2010 		groupCube->addChild(maxLodGroupCube.release());
2011 		groupCube->addChild(baseLevelGroupCube.release());
2012 		groupCube->addChild(maxLevelGroupCube.release());
2013 
2014 		textureMipmappingTests->addChild(groupCube.release());
2015 	}
2016 
2017 	// 3D cases.
2018 	{
2019 		de::MovePtr<tcu::TestCaseGroup>	group3D				(new tcu::TestCaseGroup(testCtx, "3d", "3D Mipmap Filtering"));
2020 
2021 		de::MovePtr<tcu::TestCaseGroup>	biasGroup3D			(new tcu::TestCaseGroup(testCtx, "bias", "User-supplied bias value"));
2022 		de::MovePtr<tcu::TestCaseGroup>	minLodGroup3D		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
2023 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroup3D		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
2024 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroup3D	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
2025 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroup3D		(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
2026 
2027 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
2028 		{
2029 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup	(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name, coordTypes[coordType].desc));
2030 
2031 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2032 			{
2033 				for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
2034 				{
2035 					// Add other size variants to basic cases only.
2036 					int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
2037 
2038 					Texture3DMipmapTestCaseParameters	testParameters;
2039 
2040 					testParameters.coordType		= coordTypes[coordType].type;
2041 					testParameters.minFilter		= minFilterModes[minFilter].mode;
2042 					testParameters.minFilterName	= minFilterModes[minFilter].name;
2043 					testParameters.wrapR			= wrapModes[wrapMode].mode;
2044 					testParameters.wrapS			= wrapModes[wrapMode].mode;
2045 					testParameters.wrapT			= wrapModes[wrapMode].mode;
2046 					testParameters.format			= VK_FORMAT_R8G8B8A8_UNORM;
2047 					testParameters.programs.push_back(PROGRAM_3D_FLOAT);
2048 
2049 					for (int size = 0; size < sizeEnd; size++)
2050 					{
2051 						testParameters.width			= tex3DSizes[size].width;
2052 						testParameters.height			= tex3DSizes[size].height;
2053 						testParameters.depth			= tex3DSizes[size].depth;
2054 
2055 						std::ostringstream name;
2056 						name << minFilterModes[minFilter].name
2057 							 << "_" << wrapModes[wrapMode].name;
2058 
2059 						if (tex3DSizes[size].name)
2060 							name << "_" << tex3DSizes[size].name;
2061 
2062 						coordTypeGroup->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
2063 					}
2064 				}
2065 			}
2066 
2067 			group3D->addChild(coordTypeGroup.release());
2068 		}
2069 
2070 		// 3D bias variants.
2071 		{
2072 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2073 			{
2074 				Texture3DMipmapTestCaseParameters	testParameters;
2075 				testParameters.coordType			= COORDTYPE_BASIC_BIAS;
2076 				testParameters.minFilter			= minFilterModes[minFilter].mode;
2077 				testParameters.wrapR				= Sampler::REPEAT_GL;
2078 				testParameters.wrapS				= Sampler::REPEAT_GL;
2079 				testParameters.wrapT				= Sampler::REPEAT_GL;
2080 				testParameters.format				= VK_FORMAT_R8G8B8A8_UNORM;
2081 				testParameters.width				= tex3DSizes[0].width;
2082 				testParameters.height				= tex3DSizes[0].height;
2083 				testParameters.depth				= tex3DSizes[0].depth;
2084 
2085 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
2086 				testParameters.programs.push_back(PROGRAM_3D_FLOAT_BIAS);
2087 
2088 				biasGroup3D->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
2089 			}
2090 		}
2091 
2092 		// 3D LOD controls.
2093 		{
2094 			// MIN_LOD
2095 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2096 			{
2097 				Texture3DMipmapTestCaseParameters	testParameters;
2098 				testParameters.minFilter			= minFilterModes[minFilter].mode;
2099 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
2100 
2101 				minLodGroup3D->addChild(new TextureTestCase<Texture3DMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
2102 			}
2103 
2104 			// MAX_LOD
2105 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2106 			{
2107 				Texture3DMipmapTestCaseParameters	testParameters;
2108 				testParameters.minFilter			= minFilterModes[minFilter].mode;
2109 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
2110 
2111 				maxLodGroup3D->addChild(new TextureTestCase<Texture3DMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
2112 			}
2113 		}
2114 
2115 		{
2116 			// BASE_LEVEL
2117 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2118 			{
2119 				Texture3DMipmapTestCaseParameters	testParameters;
2120 				testParameters.minFilter			= minFilterModes[minFilter].mode;
2121 				testParameters.minFilterName		= minFilterModes[minFilter].name;
2122 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
2123 
2124 				baseLevelGroup3D->addChild(new TextureTestCase<Texture3DBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
2125 			}
2126 
2127 			// MAX_LEVEL
2128 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
2129 			{
2130 				Texture3DMipmapTestCaseParameters	testParameters;
2131 				testParameters.minFilter			= minFilterModes[minFilter].mode;
2132 				testParameters.minFilterName		= minFilterModes[minFilter].name;
2133 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
2134 
2135 				maxLevelGroup3D->addChild(new TextureTestCase<Texture3DMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
2136 			}
2137 		}
2138 
2139 		group3D->addChild(biasGroup3D.release());
2140 		group3D->addChild(minLodGroup3D.release());
2141 		group3D->addChild(maxLodGroup3D.release());
2142 		group3D->addChild(baseLevelGroup3D.release());
2143 		group3D->addChild(maxLevelGroup3D.release());
2144 
2145 		textureMipmappingTests->addChild(group3D.release());
2146 	}
2147 }
2148 
2149 } // anonymous
2150 
createTextureMipmappingTests(tcu::TestContext & testCtx)2151 tcu::TestCaseGroup* createTextureMipmappingTests (tcu::TestContext& testCtx)
2152 {
2153 	return createTestGroup(testCtx, "mipmap", "Texture mipmapping tests.", populateTextureMipmappingTests);
2154 }
2155 
2156 } // texture
2157 } // vkt
2158