• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "tcuCommandLine.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkQueryUtil.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBufferWithMemory.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkBarrierUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vktTestGroupUtil.hpp"
48 #include "vktTextureTestUtil.hpp"
49 #include "vktCustomInstancesDevices.hpp"
50 
51 #include <memory>
52 
53 using namespace vk;
54 
55 namespace vkt
56 {
57 namespace texture
58 {
59 namespace
60 {
61 
62 using std::string;
63 using std::vector;
64 using tcu::TestLog;
65 using tcu::Vec2;
66 using tcu::Vec3;
67 using tcu::Vec4;
68 using tcu::IVec3;
69 using tcu::IVec4;
70 using tcu::Sampler;
71 using tcu::TextureFormat;
72 using namespace texture::util;
73 using namespace glu::TextureTestUtil;
74 
getMinLodForCell(int cellNdx)75 float getMinLodForCell (int cellNdx)
76 {
77 	static const float s_values[] =
78 	{
79 		1.0f,
80 		3.5f,
81 		2.0f,
82 		-2.0f,
83 		0.0f,
84 		3.0f,
85 		10.0f,
86 		4.8f,
87 		5.8f,
88 		5.7f,
89 		-1.9f,
90 		4.0f,
91 		6.5f,
92 		7.1f,
93 		-1e10,
94 		1000.f
95 	};
96 	return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
97 }
98 
getMaxLodForCell(int cellNdx)99 float getMaxLodForCell (int cellNdx)
100 {
101 	static const float s_values[] =
102 	{
103 		0.0f,
104 		0.2f,
105 		0.7f,
106 		0.4f,
107 		1.3f,
108 		0.0f,
109 		0.5f,
110 		1.2f,
111 		-2.0f,
112 		1.0f,
113 		0.1f,
114 		0.3f,
115 		2.7f,
116 		1.2f,
117 		10.0f,
118 		-1000.f,
119 		1e10f
120 	};
121 	return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
122 }
123 
124 enum CoordType
125 {
126 	COORDTYPE_BASIC,		//!< texCoord = translateScale(position).
127 	COORDTYPE_BASIC_BIAS,	//!< Like basic, but with bias values.
128 	COORDTYPE_AFFINE,		//!< texCoord = translateScaleRotateShear(position).
129 	COORDTYPE_PROJECTED,	//!< Projected coordinates, w != 1
130 
131 	COORDTYPE_LAST
132 };
133 
134 struct TextureMipmapCommonTestCaseParameters
135 {
136 							TextureMipmapCommonTestCaseParameters		(void);
137 	CoordType				coordType;
138 	const char*				minFilterName;
139 };
140 
TextureMipmapCommonTestCaseParameters(void)141 TextureMipmapCommonTestCaseParameters::TextureMipmapCommonTestCaseParameters (void)
142 	: coordType						(COORDTYPE_BASIC)
143 	, minFilterName					(NULL)
144 {
145 }
146 
147 struct Texture2DMipmapTestCaseParameters : public Texture2DTestCaseParameters, public TextureMipmapCommonTestCaseParameters
148 {
149 };
150 
151 struct TextureCubeMipmapTestCaseParameters : public TextureCubeTestCaseParameters, public TextureMipmapCommonTestCaseParameters
152 {
153 };
154 
155 struct Texture3DMipmapTestCaseParameters : public Texture3DTestCaseParameters, public TextureMipmapCommonTestCaseParameters
156 {
157 };
158 
159 // Texture2DMipmapTestInstance
160 class Texture2DMipmapTestInstance : public TestInstance
161 {
162 public:
163 	typedef Texture2DMipmapTestCaseParameters	ParameterType;
164 
165 									Texture2DMipmapTestInstance		(Context& context, const ParameterType& testParameters);
166 									~Texture2DMipmapTestInstance	(void);
167 
168 	virtual tcu::TestStatus			iterate							(void);
169 
170 private:
171 									Texture2DMipmapTestInstance		(const Texture2DMipmapTestInstance& other);
172 	Texture2DMipmapTestInstance&	operator=						(const Texture2DMipmapTestInstance& other);
173 
174 	const ParameterType				m_testParameters;
175 	TestTexture2DSp					m_texture;
176 	TextureRenderer					m_renderer;
177 };
178 
Texture2DMipmapTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)179 Texture2DMipmapTestInstance::Texture2DMipmapTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
180 	: TestInstance		(context)
181 	, m_testParameters	(testParameters)
182 	, m_renderer		(context, testParameters.sampleCount, testParameters.width*4, testParameters.height*4)
183 {
184 	TCU_CHECK_INTERNAL(!(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
185 
186 	m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height));
187 
188 	const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1;
189 
190 	// Fill texture with colored grid.
191 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
192 	{
193 		const deUint32	step	= 0xff / (numLevels-1);
194 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
195 		const deUint32	dec		= 0xff - inc;
196 		const deUint32	rgb		= (inc << 16) | (dec << 8) | 0xff;
197 		const deUint32	color	= 0xff000000 | rgb;
198 
199 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
200 	}
201 
202 	// Upload texture data.
203 	m_renderer.add2DTexture(m_texture, testParameters.aspectMask);
204 }
205 
~Texture2DMipmapTestInstance(void)206 Texture2DMipmapTestInstance::~Texture2DMipmapTestInstance (void)
207 {
208 }
209 
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)210 static void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
211 {
212 	static const struct
213 	{
214 		const Vec2	bottomLeft;
215 		const Vec2	topRight;
216 	} s_basicCoords[] =
217 	{
218 		{ Vec2(-0.1f,  0.1f), Vec2( 0.8f,  1.0f) },
219 		{ Vec2(-0.3f, -0.6f), Vec2( 0.7f,  0.4f) },
220 		{ Vec2(-0.3f,  0.6f), Vec2( 0.7f, -0.9f) },
221 		{ Vec2(-0.8f,  0.6f), Vec2( 0.7f, -0.9f) },
222 
223 		{ Vec2(-0.5f, -0.5f), Vec2( 1.5f,  1.5f) },
224 		{ Vec2( 1.0f, -1.0f), Vec2(-1.3f,  1.0f) },
225 		{ Vec2( 1.2f, -1.0f), Vec2(-1.3f,  1.6f) },
226 		{ Vec2( 2.2f, -1.1f), Vec2(-1.3f,  0.8f) },
227 
228 		{ Vec2(-1.5f,  1.6f), Vec2( 1.7f, -1.4f) },
229 		{ Vec2( 2.0f,  1.6f), Vec2( 2.3f, -1.4f) },
230 		{ Vec2( 1.3f, -2.6f), Vec2(-2.7f,  2.9f) },
231 		{ Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },
232 
233 		{ Vec2( -8.0f,   9.0f), Vec2(  8.3f,  -7.0f) },
234 		{ Vec2(-16.0f,  10.0f), Vec2( 18.3f,  24.0f) },
235 		{ Vec2( 30.2f,  55.0f), Vec2(-24.3f,  -1.6f) },
236 		{ Vec2(-33.2f,  64.1f), Vec2( 32.1f, -64.1f) },
237 	};
238 
239 	DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
240 
241 	const Vec2& bottomLeft	= s_basicCoords[cellNdx].bottomLeft;
242 	const Vec2& topRight	= s_basicCoords[cellNdx].topRight;
243 
244 	computeQuadTexCoord2D(dst, bottomLeft, topRight);
245 }
246 
getBasicTexCoord2DImageViewMinLodIntTexCoord(std::vector<float> & dst)247 static void getBasicTexCoord2DImageViewMinLodIntTexCoord (std::vector<float>& dst)
248 {
249 	computeQuadTexCoord2D(dst, Vec2(0.0f), Vec2(1.0f));
250 }
251 
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)252 static void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
253 {
254 	// Use basic coords as base.
255 	getBasicTexCoord2D(dst, cellNdx);
256 
257 	// Rotate based on cell index.
258 	const float		angle		= 2.0f*DE_PI * ((float)cellNdx / 16.0f);
259 	const tcu::Mat2	rotMatrix	= tcu::rotationMatrix(angle);
260 
261 	// Second and third row are sheared.
262 	const float		shearX		= de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
263 	const tcu::Mat2	shearMatrix	= tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
264 
265 	const tcu::Mat2	transform	= rotMatrix * shearMatrix;
266 	const Vec2		p0			= transform * Vec2(dst[0], dst[1]);
267 	const Vec2		p1			= transform * Vec2(dst[2], dst[3]);
268 	const Vec2		p2			= transform * Vec2(dst[4], dst[5]);
269 	const Vec2		p3			= transform * Vec2(dst[6], dst[7]);
270 
271 	dst[0] = p0.x();	dst[1] = p0.y();
272 	dst[2] = p1.x();	dst[3] = p1.y();
273 	dst[4] = p2.x();	dst[5] = p2.y();
274 	dst[6] = p3.x();	dst[7] = p3.y();
275 }
276 
iterate(void)277 tcu::TestStatus Texture2DMipmapTestInstance::iterate (void)
278 {
279 	const Sampler::FilterMode	magFilter		= Sampler::NEAREST;
280 	const int					viewportWidth	= m_renderer.getRenderWidth();
281 	const int					viewportHeight	= m_renderer.getRenderHeight();
282 
283 	ReferenceParams				refParams		(TEXTURETYPE_2D);
284 	vector<float>				texCoord;
285 
286 	const bool					isProjected		= m_testParameters.coordType == COORDTYPE_PROJECTED;
287 	const bool					useLodBias		= m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
288 
289 	tcu::Surface				renderedFrame	(viewportWidth, viewportHeight);
290 
291 	// Viewport is divided into 4x4 grid.
292 	const int					gridWidth		= 4;
293 	const int					gridHeight		= 4;
294 	const int					cellWidth		= viewportWidth / gridWidth;
295 	const int					cellHeight		= viewportHeight / gridHeight;
296 
297 	// Sampling parameters.
298 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
299 	refParams.samplerType	= getSamplerType(vk::mapVkFormat(m_testParameters.format));
300 	refParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
301 	refParams.lodMode		= LODMODE_EXACT; // Use ideal lod.
302 
303 	// Bias values.
304 	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
305 
306 	// Projection values.
307 	static const Vec4 s_projections[] =
308 	{
309 		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
310 		Vec4(1.3f, 0.8f, 0.6f, 2.0f),
311 		Vec4(0.8f, 1.0f, 1.7f, 0.6f),
312 		Vec4(1.2f, 1.0f, 1.7f, 1.5f)
313 	};
314 
315 	// Render cells.
316 	for (int gridY = 0; gridY < gridHeight; gridY++)
317 	{
318 		for (int gridX = 0; gridX < gridWidth; gridX++)
319 		{
320 			const int	curX		= cellWidth*gridX;
321 			const int	curY		= cellHeight*gridY;
322 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
323 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
324 			const int	cellNdx		= gridY*gridWidth + gridX;
325 
326 			// Compute texcoord.
327 			switch (m_testParameters.coordType)
328 			{
329 				case COORDTYPE_BASIC_BIAS:	// Fall-through.
330 				case COORDTYPE_PROJECTED:
331 				case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
332 				case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
333 				default:					DE_ASSERT(DE_FALSE);
334 			}
335 
336 			if (isProjected)
337 				refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
338 
339 			if (useLodBias)
340 				refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
341 
342 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
343 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
344 		}
345 	}
346 
347 	// Compare and log.
348 	{
349 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
350 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
351 		const bool				isTrilinear		= m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
352 		tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
353 		tcu::Surface			errorMask		(viewportWidth, viewportHeight);
354 		tcu::LookupPrecision	lookupPrec;
355 		tcu::LodPrecision		lodPrec;
356 		int						numFailedPixels	= 0;
357 
358 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
359 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
360 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
361 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
362 		lodPrec.derivateBits		= 10;
363 		lodPrec.lodBits				= isProjected ? 6 : 8;
364 
365 		for (int gridY = 0; gridY < gridHeight; gridY++)
366 		{
367 			for (int gridX = 0; gridX < gridWidth; gridX++)
368 			{
369 				const int	curX		= cellWidth*gridX;
370 				const int	curY		= cellHeight*gridY;
371 				const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
372 				const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
373 				const int	cellNdx		= gridY*gridWidth + gridX;
374 
375 				// Compute texcoord.
376 				switch (m_testParameters.coordType)
377 				{
378 					case COORDTYPE_BASIC_BIAS:	// Fall-through.
379 					case COORDTYPE_PROJECTED:
380 					case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
381 					case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
382 					default:					DE_ASSERT(DE_FALSE);
383 				}
384 
385 				if (isProjected)
386 					refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
387 
388 				if (useLodBias)
389 					refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
390 
391 				// Render ideal result
392 				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
393 							  m_texture->getTexture(), &texCoord[0], refParams);
394 
395 				// Compare this cell
396 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
397 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
398 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
399 															m_texture->getTexture(), &texCoord[0], refParams,
400 															lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
401 			}
402 		}
403 
404 		if (numFailedPixels > 0)
405 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
406 
407 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
408 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
409 
410 		if (numFailedPixels > 0)
411 		{
412 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
413 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
414 		}
415 
416 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
417 
418 		{
419 			const bool isOk = numFailedPixels == 0;
420 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
421 		}
422 	}
423 }
424 
425 // TextureCubeMipmapTestInstance
426 class TextureCubeMipmapTestInstance : public TestInstance
427 {
428 public:
429 	typedef	TextureCubeMipmapTestCaseParameters	ParameterType;
430 
431 									TextureCubeMipmapTestInstance	(Context& context, const ParameterType& testParameters);
432 									~TextureCubeMipmapTestInstance	(void);
433 
434 	virtual tcu::TestStatus			iterate							(void);
435 
436 private:
437 									TextureCubeMipmapTestInstance	(const TextureCubeMipmapTestInstance& other);
438 	TextureCubeMipmapTestInstance&	operator=						(const TextureCubeMipmapTestInstance& other);
439 
440 	const ParameterType				m_testParameters;
441 	TestTextureCubeSp				m_texture;
442 	TextureRenderer					m_renderer;
443 };
444 
TextureCubeMipmapTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)445 TextureCubeMipmapTestInstance::TextureCubeMipmapTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
446 	: TestInstance		(context)
447 	, m_testParameters	(testParameters)
448 	, m_renderer		(context, m_testParameters.sampleCount, m_testParameters.size*2, m_testParameters.size*2)
449 {
450 	TCU_CHECK_INTERNAL(!(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
451 
452 	m_texture = TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size));
453 
454 	const int numLevels = deLog2Floor32(m_testParameters.size)+1;
455 
456 	// Fill texture with colored grid.
457 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
458 	{
459 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
460 		{
461 			const deUint32	step	= 0xff / (numLevels-1);
462 			const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
463 			const deUint32	dec		= 0xff - inc;
464 			deUint32		rgb		= 0;
465 
466 			switch (faceNdx)
467 			{
468 				case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
469 				case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
470 				case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
471 				case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
472 				case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
473 				case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
474 			}
475 
476 			const deUint32	color	= 0xff000000 | rgb;
477 			tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
478 		}
479 	}
480 
481 	m_renderer.addCubeTexture(m_texture, testParameters.aspectMask);
482 }
483 
~TextureCubeMipmapTestInstance(void)484 TextureCubeMipmapTestInstance::~TextureCubeMipmapTestInstance (void)
485 {
486 }
487 
randomPartition(vector<IVec4> & dst,de::Random & rnd,int x,int y,int width,int height)488 static void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
489 {
490 	const int	minWidth	= 8;
491 	const int	minHeight	= 8;
492 
493 	const bool	partition	= rnd.getFloat() > 0.4f;
494 	const bool	partitionX	= partition && width > minWidth && rnd.getBool();
495 	const bool	partitionY	= partition && height > minHeight && !partitionX;
496 
497 	if (partitionX)
498 	{
499 		const int split = width/2 + rnd.getInt(-width/4, +width/4);
500 		randomPartition(dst, rnd, x, y, split, height);
501 		randomPartition(dst, rnd, x+split, y, width-split, height);
502 	}
503 	else if (partitionY)
504 	{
505 		const int split = height/2 + rnd.getInt(-height/4, +height/4);
506 		randomPartition(dst, rnd, x, y, width, split);
507 		randomPartition(dst, rnd, x, y+split, width, height-split);
508 	}
509 	else
510 		dst.push_back(IVec4(x, y, width, height));
511 }
512 
computeGridLayout(vector<IVec4> & dst,int width,int height)513 static void computeGridLayout (vector<IVec4>& dst, int width, int height)
514 {
515 	de::Random rnd(7);
516 	randomPartition(dst, rnd, 0, 0, width, height);
517 }
518 
iterate(void)519 tcu::TestStatus TextureCubeMipmapTestInstance::iterate (void)
520 {
521 	const int			viewportWidth	= m_renderer.getRenderWidth();
522 	const int			viewportHeight	= m_renderer.getRenderHeight();
523 
524 	const bool			isProjected		= m_testParameters.coordType == COORDTYPE_PROJECTED;
525 	const bool			useLodBias		= m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
526 
527 	ReferenceParams		refParams		(TEXTURETYPE_CUBE);
528 	vector<float>		texCoord;
529 	tcu::Surface		renderedFrame	(viewportWidth, viewportHeight);
530 
531 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
532 	refParams.samplerType	= getSamplerType(vk::mapVkFormat(m_testParameters.format));
533 	refParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
534 	refParams.lodMode		= LODMODE_EXACT; // Use ideal lod.
535 
536 	// Compute grid.
537 	vector<IVec4> gridLayout;
538 	computeGridLayout(gridLayout, viewportWidth, viewportHeight);
539 
540 	// Bias values.
541 	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
542 
543 	// Projection values \note Less agressive than in 2D case due to smaller quads.
544 	static const Vec4 s_projections[] =
545 	{
546 		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
547 		Vec4(1.3f, 0.8f, 0.6f, 1.1f),
548 		Vec4(0.8f, 1.0f, 1.2f, 0.8f),
549 		Vec4(1.2f, 1.0f, 1.3f, 0.9f)
550 	};
551 
552 	// Render with GL
553 	for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
554 	{
555 		const float			curX		= (float)gridLayout[cellNdx].x();
556 		const float			curY		= (float)gridLayout[cellNdx].y();
557 		const float			curW		= (float)gridLayout[cellNdx].z();
558 		const float			curH		= (float)gridLayout[cellNdx].w();
559 		const tcu::CubeFace	cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
560 
561 		DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
562 		computeQuadTexCoordCube(texCoord, cubeFace);
563 
564 		if (isProjected)
565 		{
566 			refParams.flags	|= ReferenceParams::PROJECTED;
567 			refParams.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
568 		}
569 
570 		if (useLodBias)
571 		{
572 			refParams.flags	|= ReferenceParams::USE_BIAS;
573 			refParams.bias	 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
574 		}
575 
576 		// Render
577 		m_renderer.setViewport(curX, curY, curW, curH);
578 		m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
579 	}
580 
581 	// Render reference and compare
582 	{
583 		const tcu::IVec4		formatBitDepth		= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
584 		const tcu::PixelFormat	pixelFormat			(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
585 		tcu::Surface			referenceFrame		(viewportWidth, viewportHeight);
586 		tcu::Surface			errorMask			(viewportWidth, viewportHeight);
587 		int						numFailedPixels		= 0;
588 		tcu::LookupPrecision	lookupPrec;
589 		tcu::LodPrecision		lodPrec;
590 
591 		// Params for rendering reference
592 		refParams.sampler					= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
593 		refParams.sampler.seamlessCubeMap	= true;
594 		refParams.lodMode					= LODMODE_EXACT;
595 
596 		// Comparison parameters
597 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
598 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat)-2, tcu::IVec4(0)));
599 		lookupPrec.coordBits		= isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
600 		lookupPrec.uvwBits			= tcu::IVec3(5,5,0);
601 		lodPrec.derivateBits		= 10;
602 		lodPrec.lodBits				= isProjected ? 3 : 6;
603 
604 		for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
605 		{
606 			const int				curX		= gridLayout[cellNdx].x();
607 			const int				curY		= gridLayout[cellNdx].y();
608 			const int				curW		= gridLayout[cellNdx].z();
609 			const int				curH		= gridLayout[cellNdx].w();
610 			const tcu::CubeFace		cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
611 
612 			DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
613 			computeQuadTexCoordCube(texCoord, cubeFace);
614 
615 			if (isProjected)
616 			{
617 				refParams.flags	|= ReferenceParams::PROJECTED;
618 				refParams.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
619 			}
620 
621 			if (useLodBias)
622 			{
623 				refParams.flags	|= ReferenceParams::USE_BIAS;
624 				refParams.bias	 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
625 			}
626 
627 			// Render ideal reference.
628 			{
629 				tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
630 				sampleTexture(idealDst, m_texture->getTexture(), &texCoord[0], refParams);
631 			}
632 
633 			// Compare this cell
634 			numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
635 														tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
636 														tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
637 														m_texture->getTexture(), &texCoord[0], refParams,
638 														lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
639 		}
640 
641 		if (numFailedPixels > 0)
642 		{
643 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
644 		}
645 
646 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
647 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
648 
649 		if (numFailedPixels > 0)
650 		{
651 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
652 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
653 		}
654 
655 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
656 
657 		{
658 			const bool isOk = numFailedPixels == 0;
659 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
660 		}
661 	}
662 }
663 
664 // Texture3DMipmapTestInstance
665 class Texture3DMipmapTestInstance : public TestInstance
666 {
667 public:
668 	typedef Texture3DMipmapTestCaseParameters	ParameterType;
669 
670 									Texture3DMipmapTestInstance		(Context& context, const ParameterType& testParameters);
671 									~Texture3DMipmapTestInstance	(void);
672 
673 	virtual tcu::TestStatus			iterate							(void);
674 
675 private:
676 									Texture3DMipmapTestInstance		(const Texture3DMipmapTestInstance& other);
677 	Texture3DMipmapTestInstance&	operator=						(const Texture3DMipmapTestInstance& other);
678 
679 	const ParameterType				m_testParameters;
680 	TestTexture3DSp					m_texture;
681 	TextureRenderer					m_renderer;
682 };
683 
Texture3DMipmapTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)684 Texture3DMipmapTestInstance::Texture3DMipmapTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
685 	: TestInstance		(context)
686 	, m_testParameters	(testParameters)
687 	, m_renderer		(context, testParameters.sampleCount, testParameters.width*4, testParameters.height*4)
688 {
689 	TCU_CHECK_INTERNAL(!(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
690 
691 	const tcu::TextureFormat&	texFmt		= mapVkFormat(testParameters.format);
692 	tcu::TextureFormatInfo		fmtInfo		= tcu::getTextureFormatInfo(texFmt);
693 	const tcu::Vec4&			cScale		= fmtInfo.lookupScale;
694 	const tcu::Vec4&			cBias		= fmtInfo.lookupBias;
695 	const int					numLevels	= deLog2Floor32(de::max(de::max(testParameters.width, testParameters.height), testParameters.depth))+1;
696 
697 	m_texture = TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.depth));
698 
699 	// Fill texture with colored grid.
700 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
701 	{
702 		const deUint32	step	= 0xff / (numLevels-1);
703 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
704 		const deUint32	dec		= 0xff - inc;
705 		const deUint32	rgb		= (0xff << 16) | (dec << 8) | inc;
706 		const deUint32	color	= 0xff000000 | rgb;
707 
708 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec()*cScale + cBias);
709 	}
710 
711 	m_renderer.add3DTexture(m_texture, testParameters.aspectMask);
712 }
713 
~Texture3DMipmapTestInstance(void)714 Texture3DMipmapTestInstance::~Texture3DMipmapTestInstance (void)
715 {
716 }
717 
getBasicTexCoord3D(std::vector<float> & dst,int cellNdx)718 static void getBasicTexCoord3D (std::vector<float>& dst, int cellNdx)
719 {
720 	static const struct
721 	{
722 		const float sScale;
723 		const float sBias;
724 		const float tScale;
725 		const float tBias;
726 		const float rScale;
727 		const float rBias;
728 	} s_params[] =
729 	{
730 	//		sScale	sBias	tScale	tBias	rScale	rBias
731 		{	 0.9f,	-0.1f,	 0.7f,	 0.3f,	 0.8f,	 0.9f	},
732 		{	 1.2f,	-0.1f,	 1.1f,	 0.3f,	 1.0f,	 0.9f	},
733 		{	 1.5f,	 0.7f,	 0.9f,	-0.3f,	 1.1f,	 0.1f	},
734 		{	 1.2f,	 0.7f,	-2.3f,	-0.3f,	 1.1f,	 0.2f	},
735 		{	 1.1f,	 0.8f,	-1.3f,	-0.3f,	 2.9f,	 0.9f	},
736 		{	 3.4f,	 0.8f,	 4.0f,	 0.0f,	-3.3f,	-1.0f	},
737 		{	-3.4f,	-0.1f,	-4.0f,	 0.0f,	-5.1f,	 1.0f	},
738 		{	-4.0f,	-0.1f,	 3.4f,	 0.1f,	 5.7f,	 0.0f	},
739 		{	-5.6f,	 0.0f,	 0.5f,	 1.2f,	 3.9f,	 4.0f	},
740 		{	 5.0f,	-2.0f,	 3.1f,	 1.2f,	 5.1f,	 0.2f	},
741 		{	 2.5f,	-2.0f,	 6.3f,	 3.0f,	 5.1f,	 0.2f	},
742 		{	-8.3f,	 0.0f,	 7.1f,	 3.0f,	 2.0f,	 0.2f	},
743 		{	 3.8f,	 0.0f,	 9.7f,	 1.0f,	 7.0f,	 0.7f	},
744 		{	13.3f,	 0.0f,	 7.1f,	 3.0f,	 2.0f,	 0.2f	},
745 		{	16.0f,	 8.0f,	12.7f,	 1.0f,	17.1f,	 0.7f	},
746 		{	15.3f,	 0.0f,	20.1f,	 3.0f,	33.0f,	 3.2f	}
747 	};
748 
749 	const float sScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sScale;
750 	const float sBias	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].sBias;
751 	const float tScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tScale;
752 	const float tBias	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].tBias;
753 	const float rScale	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rScale;
754 	const float rBias	= s_params[cellNdx%DE_LENGTH_OF_ARRAY(s_params)].rBias;
755 
756 	dst.resize(3*4);
757 
758 	dst[0] = sBias;			dst[ 1] = tBias;			dst[ 2] = rBias;
759 	dst[3] = sBias;			dst[ 4] = tBias+tScale;		dst[ 5] = rBias+rScale*0.5f;
760 	dst[6] = sBias+sScale;	dst[ 7] = tBias;			dst[ 8] = rBias+rScale*0.5f;
761 	dst[9] = sBias+sScale;	dst[10] = tBias+tScale;		dst[11] = rBias+rScale;
762 }
763 
getBasicTexCoord3DImageViewMinlodIntTexCoord(std::vector<float> & dst)764 static void getBasicTexCoord3DImageViewMinlodIntTexCoord (std::vector<float>& dst)
765 {
766 	const float sScale	= 1.0f;
767 	const float sBias	= 0.0f;
768 	const float tScale	= 1.0f;
769 	const float tBias	= 0.0f;
770 	const float rScale	= 1.0f;
771 	const float rBias	= 0.0f;
772 
773 	dst.resize(3*4);
774 
775 	dst[0] = sBias;			dst[ 1] = tBias;			dst[ 2] = rBias;
776 	dst[3] = sBias;			dst[ 4] = tBias+tScale;		dst[ 5] = rBias+rScale*0.5f;
777 	dst[6] = sBias+sScale;	dst[ 7] = tBias;			dst[ 8] = rBias+rScale*0.5f;
778 	dst[9] = sBias+sScale;	dst[10] = tBias+tScale;		dst[11] = rBias+rScale;
779 }
780 
getAffineTexCoord3D(std::vector<float> & dst,int cellNdx)781 static void getAffineTexCoord3D (std::vector<float>& dst, int cellNdx)
782 {
783 	// Use basic coords as base.
784 	getBasicTexCoord3D(dst, cellNdx);
785 
786 	// Rotate based on cell index.
787 	const float		angleX		= 0.0f + 2.0f*DE_PI * ((float)cellNdx / 16.0f);
788 	const float		angleY		= 1.0f + 2.0f*DE_PI * ((float)cellNdx / 32.0f);
789 	const tcu::Mat3	rotMatrix	= tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);
790 
791 	const Vec3		p0			= rotMatrix * Vec3(dst[0], dst[ 1], dst[ 2]);
792 	const Vec3		p1			= rotMatrix * Vec3(dst[3], dst[ 4], dst[ 5]);
793 	const Vec3		p2			= rotMatrix * Vec3(dst[6], dst[ 7], dst[ 8]);
794 	const Vec3		p3			= rotMatrix * Vec3(dst[9], dst[10], dst[11]);
795 
796 	dst[0] = p0.x();	dst[ 1] = p0.y();	dst[ 2] = p0.z();
797 	dst[3] = p1.x();	dst[ 4] = p1.y();	dst[ 5] = p1.z();
798 	dst[6] = p2.x();	dst[ 7] = p2.y();	dst[ 8] = p2.z();
799 	dst[9] = p3.x();	dst[10] = p3.y();	dst[11] = p3.z();
800 }
801 
iterate(void)802 tcu::TestStatus Texture3DMipmapTestInstance::iterate (void)
803 {
804 	const tcu::TextureFormat&		texFmt			= m_texture->getTextureFormat();
805 	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
806 	const Sampler::FilterMode		magFilter		= Sampler::NEAREST;
807 	const int						viewportWidth	= m_renderer.getRenderWidth();
808 	const int						viewportHeight	= m_renderer.getRenderHeight();
809 
810 	const bool						isProjected		= m_testParameters.coordType == COORDTYPE_PROJECTED;
811 	const bool						useLodBias		= m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
812 
813 	// Viewport is divided into 4x4 grid.
814 	const int						gridWidth		= 4;
815 	const int						gridHeight		= 4;
816 	const int						cellWidth		= viewportWidth / gridWidth;
817 	const int						cellHeight		= viewportHeight / gridHeight;
818 
819 	ReferenceParams					refParams		(TEXTURETYPE_3D);
820 
821 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
822 	vector<float>					texCoord;
823 
824 	// Sampling parameters.
825 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
826 	refParams.samplerType	= getSamplerType(texFmt);
827 
828 	refParams.colorBias		= fmtInfo.lookupBias;
829 	refParams.colorScale	= fmtInfo.lookupScale;
830 	refParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
831 
832 	// Bias values.
833 	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
834 
835 	// Projection values.
836 	static const Vec4 s_projections[] =
837 	{
838 		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
839 		Vec4(1.3f, 0.8f, 0.6f, 2.0f),
840 		Vec4(0.8f, 1.0f, 1.7f, 0.6f),
841 		Vec4(1.2f, 1.0f, 1.7f, 1.5f)
842 	};
843 
844 	// Render cells.
845 	for (int gridY = 0; gridY < gridHeight; gridY++)
846 	{
847 		for (int gridX = 0; gridX < gridWidth; gridX++)
848 		{
849 			const int	curX		= cellWidth*gridX;
850 			const int	curY		= cellHeight*gridY;
851 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
852 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
853 			const int	cellNdx		= gridY*gridWidth + gridX;
854 
855 			// Compute texcoord.
856 			switch (m_testParameters.coordType)
857 			{
858 				case COORDTYPE_BASIC_BIAS:	// Fall-through.
859 				case COORDTYPE_PROJECTED:
860 				case COORDTYPE_BASIC:		getBasicTexCoord3D	(texCoord, cellNdx);	break;
861 				case COORDTYPE_AFFINE:		getAffineTexCoord3D	(texCoord, cellNdx);	break;
862 				default:					DE_ASSERT(DE_FALSE);
863 			}
864 
865 			// Set projection.
866 			if (isProjected)
867 				refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
868 
869 			// Set LOD bias.
870 			if (useLodBias)
871 				refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
872 
873 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
874 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
875 		}
876 	}
877 
878 	// Compare and log
879 	{
880 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
881 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
882 		const bool				isTrilinear		= m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
883 		tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
884 		tcu::Surface			errorMask		(viewportWidth, viewportHeight);
885 		tcu::LookupPrecision	lookupPrec;
886 		tcu::LodPrecision		lodPrec;
887 		int						numFailedPixels	= 0;
888 
889 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 20);
890 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
891 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
892 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
893 		lodPrec.derivateBits		= 10;
894 		lodPrec.lodBits				= isProjected ? 6 : 8;
895 
896 		for (int gridY = 0; gridY < gridHeight; gridY++)
897 		{
898 			for (int gridX = 0; gridX < gridWidth; gridX++)
899 			{
900 				const int	curX		= cellWidth*gridX;
901 				const int	curY		= cellHeight*gridY;
902 				const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
903 				const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
904 				const int	cellNdx		= gridY*gridWidth + gridX;
905 
906 				switch (m_testParameters.coordType)
907 				{
908 					case COORDTYPE_BASIC_BIAS:	// Fall-through.
909 					case COORDTYPE_PROJECTED:
910 					case COORDTYPE_BASIC:		getBasicTexCoord3D	(texCoord, cellNdx);	break;
911 					case COORDTYPE_AFFINE:		getAffineTexCoord3D	(texCoord, cellNdx);	break;
912 					default:					DE_ASSERT(DE_FALSE);
913 				}
914 
915 				if (isProjected)
916 					refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
917 
918 				if (useLodBias)
919 					refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
920 
921 				// Render ideal result
922 				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
923 							  m_texture->getTexture(), &texCoord[0], refParams);
924 
925 				// Compare this cell
926 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
927 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
928 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
929 															m_texture->getTexture(), &texCoord[0], refParams,
930 															lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
931 			}
932 		}
933 
934 		if (numFailedPixels > 0)
935 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
936 
937 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
938 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
939 
940 		if (numFailedPixels > 0)
941 		{
942 			m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
943 												<< TestLog::Image("ErrorMask", "Error mask", errorMask);
944 		}
945 
946 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
947 
948 		{
949 			const bool isOk = numFailedPixels == 0;
950 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
951 		}
952 	}
953 }
954 
955 // Texture2DLodControlTestInstance
956 class Texture2DLodControlTestInstance : public TestInstance
957 {
958 public:
959 	typedef Texture2DMipmapTestCaseParameters	ParameterType;
960 
961 										Texture2DLodControlTestInstance		(Context& context, const ParameterType& testParameters);
962 										~Texture2DLodControlTestInstance	(void);
963 
964 	virtual tcu::TestStatus				iterate								(void);
965 
966 protected:
967 	virtual void						getReferenceParams					(ReferenceParams& params, int cellNdx) = 0;
968 
969 	const int							m_texWidth;
970 	const int							m_texHeight;
971 
972 private:
973 										Texture2DLodControlTestInstance		(const Texture2DLodControlTestInstance& other);
974 	Texture2DLodControlTestInstance&	operator=							(const Texture2DLodControlTestInstance& other);
975 
976 	const ParameterType					m_testParameters;
977 	tcu::Sampler::FilterMode			m_minFilter;
978 	TestTexture2DSp						m_texture;
979 	TextureRenderer						m_renderer;
980 };
981 
Texture2DLodControlTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)982 Texture2DLodControlTestInstance::Texture2DLodControlTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
983 	: TestInstance		(context)
984 	, m_texWidth		(64) //64
985 	, m_texHeight		(64)//64
986 	, m_testParameters	(testParameters)
987 	, m_minFilter		(testParameters.minFilter)
988 	, m_texture			(DE_NULL)
989 	, m_renderer		(context, testParameters.sampleCount, m_texWidth*4, m_texHeight*4, vk::makeComponentMappingRGBA(), testParameters.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD, testParameters.testType >= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD)
990 {
991 	const VkFormat	format		= VK_FORMAT_R8G8B8A8_UNORM;
992 	const int		numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
993 
994 	m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(format), m_texWidth, m_texHeight));
995 
996 	// Fill texture with colored grid.
997 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
998 	{
999 		const deUint32	step	= 0xff / (numLevels-1);
1000 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
1001 		const deUint32	dec		= 0xff - inc;
1002 		const deUint32	rgb		= (inc << 16) | (dec << 8) | 0xff;
1003 		const deUint32	color	= 0xff000000 | rgb;
1004 
1005 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
1006 	}
1007 
1008 	m_renderer.add2DTexture(m_texture, testParameters.aspectMask);
1009 }
1010 
~Texture2DLodControlTestInstance(void)1011 Texture2DLodControlTestInstance::~Texture2DLodControlTestInstance (void)
1012 {
1013 }
1014 
iterate(void)1015 tcu::TestStatus Texture2DLodControlTestInstance::iterate (void)
1016 {
1017 	const tcu::Sampler::WrapMode	wrapS			= Sampler::REPEAT_GL;
1018 	const tcu::Sampler::WrapMode	wrapT			= Sampler::REPEAT_GL;
1019 	const tcu::Sampler::FilterMode	magFilter		= Sampler::NEAREST;
1020 
1021 	const tcu::Texture2D&			refTexture		= m_texture->getTexture();
1022 
1023 	const int						viewportWidth	= m_renderer.getRenderWidth();
1024 	const int						viewportHeight	= m_renderer.getRenderHeight();
1025 
1026 	tcu::Sampler					sampler			= util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1027 
1028 	ReferenceParams					refParams		(TEXTURETYPE_2D, sampler);
1029 	vector<float>					texCoord;
1030 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
1031 
1032 	// Viewport is divided into 4x4 grid.
1033 	const int						gridWidth		= 4;
1034 	const int						gridHeight		= 4;
1035 	const int						cellWidth		= viewportWidth / gridWidth;
1036 	const int						cellHeight		= viewportHeight / gridHeight;
1037 
1038 	refParams.maxLevel = deLog2Floor32(de::max(m_texWidth, m_texHeight));
1039 
1040 	// Render cells.
1041 	for (int gridY = 0; gridY < gridHeight; gridY++)
1042 	{
1043 		for (int gridX = 0; gridX < gridWidth; gridX++)
1044 		{
1045 			const int	curX		= cellWidth*gridX;
1046 			const int	curY		= cellHeight*gridY;
1047 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1048 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1049 			const int	cellNdx		= gridY*gridWidth + gridX;
1050 
1051 			getReferenceParams(refParams,cellNdx);
1052 
1053 			// Compute texcoord.
1054 			getBasicTexCoord2D(texCoord, cellNdx);
1055 			// Render
1056 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1057 			m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel, refParams.imageViewMinLod);
1058 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1059 		}
1060 	}
1061 
1062 	// Compare and log.
1063 	{
1064 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1065 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1066 		const bool				isTrilinear		= m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1067 		tcu::LookupPrecision	lookupPrec;
1068 		tcu::LodPrecision		lodPrec;
1069 
1070 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
1071 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
1072 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1073 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
1074 		lodPrec.derivateBits		= 10;
1075 		lodPrec.lodBits				= 8;
1076 
1077 		auto compareAndLogImages = [&] (tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1078 		{
1079 			tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
1080 			tcu::Surface			errorMask		(viewportWidth, viewportHeight);
1081 
1082 			int						numFailedPixels = 0;
1083 
1084 			for (int gridY = 0; gridY < gridHeight; gridY++)
1085 			{
1086 				for (int gridX = 0; gridX < gridWidth; gridX++)
1087 				{
1088 					const int	curX		= cellWidth*gridX;
1089 					const int	curY		= cellHeight*gridY;
1090 					const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1091 					const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1092 					const int	cellNdx		= gridY*gridWidth + gridX;
1093 
1094 					getReferenceParams(refParams,cellNdx);
1095 
1096 					refParams.imageViewMinLodMode = imageViewLodMode;
1097 
1098 					// Compute texcoord.
1099 					if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
1100 						getBasicTexCoord2DImageViewMinLodIntTexCoord(texCoord);
1101 					else
1102 						getBasicTexCoord2D(texCoord, cellNdx);
1103 
1104 					// Render ideal result
1105 					sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
1106 								  refTexture, &texCoord[0], refParams);
1107 
1108 					// Compare this cell
1109 					numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1110 																tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1111 																tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1112 																m_texture->getTexture(), &texCoord[0], refParams,
1113 																lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1114 				}
1115 			}
1116 
1117 			if (numFailedPixels > 0)
1118 			{
1119 				m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1120 													<< TestLog::Image("ErrorMask", "Error mask", errorMask);
1121 			}
1122 			return numFailedPixels;
1123 		};
1124 
1125 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1126 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
1127 
1128 		int numFailedPixels = compareAndLogImages();
1129 
1130 		if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1131 		{
1132 			numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1133 		}
1134 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
1135 
1136 		if (numFailedPixels > 0)
1137 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1138 
1139 		{
1140 			const bool isOk = numFailedPixels == 0;
1141 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1142 		}
1143 	}
1144 }
1145 
1146 class Texture2DMinLodTestInstance : public Texture2DLodControlTestInstance
1147 {
1148 public:
Texture2DMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1149 	Texture2DMinLodTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1150 		: Texture2DLodControlTestInstance(context, testParameters)
1151 	{
1152 	}
1153 
1154 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1155 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1156 	{
1157 		params.minLod = getMinLodForCell(cellNdx);
1158 	}
1159 };
1160 
1161 class Texture2DMaxLodTestInstance : public Texture2DLodControlTestInstance
1162 {
1163 public:
Texture2DMaxLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1164 	Texture2DMaxLodTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1165 		: Texture2DLodControlTestInstance(context, testParameters)
1166 	{
1167 	}
1168 
1169 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1170 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1171 	{
1172 		params.maxLod = getMaxLodForCell(cellNdx);
1173 	}
1174 };
1175 
1176 class Texture2DBaseLevelTestInstance : public Texture2DLodControlTestInstance
1177 {
1178 public:
Texture2DBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1179 	Texture2DBaseLevelTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1180 		: Texture2DLodControlTestInstance(context, testParameters)
1181 		, m_testParam (testParameters)
1182 	{
1183 	}
1184 
1185 protected:
1186 	const Texture2DMipmapTestCaseParameters m_testParam;
1187 
getBaseLevel(int cellNdx) const1188 	int getBaseLevel (int cellNdx) const
1189 	{
1190 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1191 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1192 
1193 		return baseLevel;
1194 	}
1195 
getReferenceParams(ReferenceParams & params,int cellNdx)1196 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1197 	{
1198 		params.baseLevel = getBaseLevel(cellNdx);
1199 	}
1200 };
1201 
1202 class Texture2DMaxLevelTestInstance : public Texture2DLodControlTestInstance
1203 {
1204 public:
Texture2DMaxLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1205 	Texture2DMaxLevelTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1206 		: Texture2DLodControlTestInstance(context, testParameters)
1207 		, m_testParam (testParameters)
1208 	{
1209 	}
1210 
1211 protected:
1212 	const Texture2DMipmapTestCaseParameters m_testParam;
1213 
getMaxLevel(int cellNdx) const1214 	int getMaxLevel (int cellNdx) const
1215 	{
1216 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1217 		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x82cfa4e) % numLevels;
1218 
1219 		return maxLevel;
1220 	}
1221 
getReferenceParams(ReferenceParams & params,int cellNdx)1222 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1223 	{
1224 		params.maxLevel = getMaxLevel(cellNdx);
1225 	}
1226 };
1227 
1228 // TextureCubeLodControlTestInstance
1229 class TextureCubeLodControlTestInstance : public TestInstance
1230 {
1231 public:
1232 	typedef TextureCubeMipmapTestCaseParameters	ParameterType;
1233 
1234 										TextureCubeLodControlTestInstance	(Context& context, const ParameterType& testParameters);
1235 										~TextureCubeLodControlTestInstance	(void);
1236 
1237 	virtual tcu::TestStatus				iterate								(void);
1238 
1239 protected:
1240 	virtual void						getReferenceParams					(ReferenceParams& params, int cellNdx)	= DE_NULL;
1241 
1242 	const int							m_texSize;
1243 
1244 private:
1245 										TextureCubeLodControlTestInstance	(const TextureCubeLodControlTestInstance& other);
1246 	TextureCubeLodControlTestInstance&	operator=							(const TextureCubeLodControlTestInstance& other);
1247 
1248 	const ParameterType					m_testParameters;
1249 	tcu::Sampler::FilterMode			m_minFilter;
1250 	TestTextureCubeSp					m_texture;
1251 	TextureRenderer						m_renderer;
1252 };
1253 
TextureCubeLodControlTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1254 TextureCubeLodControlTestInstance::TextureCubeLodControlTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1255 	: TestInstance		(context)
1256 	, m_texSize			(64)
1257 	, m_testParameters	(testParameters)
1258 	, m_minFilter		(testParameters.minFilter)
1259 	, m_texture			(DE_NULL)
1260 
1261 	, m_renderer		(context, testParameters.sampleCount, m_texSize*2, m_texSize*2)
1262 {
1263 	const VkFormat	format		= VK_FORMAT_R8G8B8A8_UNORM;
1264 	const int		numLevels	= deLog2Floor32(m_texSize)+1;
1265 
1266 	m_texture = TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(format), m_texSize));
1267 
1268 	// Fill texture with colored grid.
1269 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1270 	{
1271 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1272 		{
1273 			const deUint32	step	= 0xff / (numLevels-1);
1274 			const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
1275 			const deUint32	dec		= 0xff - inc;
1276 			deUint32		rgb		= 0;
1277 
1278 			switch (faceNdx)
1279 			{
1280 				case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
1281 				case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
1282 				case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
1283 				case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
1284 				case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
1285 				case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
1286 			}
1287 
1288 			const deUint32	color	= 0xff000000 | rgb;
1289 
1290 			tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
1291 		}
1292 	}
1293 
1294 	m_renderer.addCubeTexture(m_texture, testParameters.aspectMask);
1295 }
1296 
~TextureCubeLodControlTestInstance(void)1297 TextureCubeLodControlTestInstance::~TextureCubeLodControlTestInstance (void)
1298 {
1299 }
1300 
iterate(void)1301 tcu::TestStatus TextureCubeLodControlTestInstance::iterate (void)
1302 {
1303 	const tcu::Sampler::WrapMode	wrapS			= Sampler::CLAMP_TO_EDGE;
1304 	const tcu::Sampler::WrapMode	wrapT			= Sampler::CLAMP_TO_EDGE;
1305 	const tcu::Sampler::FilterMode	magFilter		= Sampler::NEAREST;
1306 
1307 	const tcu::TextureCube&			refTexture		= m_texture->getTexture();
1308 	const int						viewportWidth	= m_renderer.getRenderWidth();
1309 	const int						viewportHeight	= m_renderer.getRenderHeight();
1310 
1311 	tcu::Sampler					sampler			= util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1312 	ReferenceParams					refParams		(TEXTURETYPE_CUBE, sampler);
1313 	vector<float>					texCoord;
1314 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
1315 
1316 	refParams.maxLevel = deLog2Floor32(m_texSize);
1317 
1318 	// Compute grid.
1319 	vector<tcu::IVec4> gridLayout;
1320 	computeGridLayout(gridLayout, viewportWidth, viewportHeight);
1321 
1322 	for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1323 	{
1324 		const int			curX		= gridLayout[cellNdx].x();
1325 		const int			curY		= gridLayout[cellNdx].y();
1326 		const int			curW		= gridLayout[cellNdx].z();
1327 		const int			curH		= gridLayout[cellNdx].w();
1328 		const tcu::CubeFace	cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1329 
1330 		computeQuadTexCoordCube(texCoord, cubeFace);
1331 		getReferenceParams(refParams, cellNdx);
1332 
1333 		// Render with GL.
1334 		m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1335 		m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel, refParams.imageViewMinLod);
1336 		m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1337 	}
1338 
1339 	// Render reference and compare
1340 	{
1341 		const tcu::IVec4		formatBitDepth		= getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1342 		const tcu::PixelFormat	pixelFormat			(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1343 		tcu::LookupPrecision	lookupPrec;
1344 		tcu::LodPrecision		lodPrec;
1345 
1346 		// Params for rendering reference
1347 		refParams.sampler					= util::createSampler(wrapS, wrapT, m_testParameters.minFilter, magFilter);
1348 		refParams.sampler.seamlessCubeMap	= true;
1349 		refParams.lodMode					= LODMODE_EXACT;
1350 
1351 		// Comparison parameters
1352 		lookupPrec.colorMask				= getCompareMask(pixelFormat);
1353 		lookupPrec.colorThreshold			= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat)-2, IVec4(0)));
1354 		lookupPrec.coordBits				= tcu::IVec3(10);
1355 		lookupPrec.uvwBits					= tcu::IVec3(5,5,0);
1356 		lodPrec.derivateBits				= 10;
1357 		lodPrec.lodBits						= 6;
1358 
1359 		auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1360 		{
1361 			tcu::Surface			referenceFrame(viewportWidth, viewportHeight);
1362 			tcu::Surface			errorMask(viewportWidth, viewportHeight);
1363 			int						numFailedPixels = 0;
1364 
1365 			for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1366 			{
1367 				const int				curX		= gridLayout[cellNdx].x();
1368 				const int				curY		= gridLayout[cellNdx].y();
1369 				const int				curW		= gridLayout[cellNdx].z();
1370 				const int				curH		= gridLayout[cellNdx].w();
1371 				const tcu::CubeFace		cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1372 
1373 				computeQuadTexCoordCube(texCoord, cubeFace);
1374 				getReferenceParams(refParams, cellNdx);
1375 
1376 				refParams.imageViewMinLodMode = imageViewLodMode;
1377 
1378 				// Render ideal reference.
1379 				{
1380 					tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
1381 					sampleTexture(idealDst, refTexture, &texCoord[0], refParams);
1382 				}
1383 
1384 				// Compare this cell
1385 				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1386 															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1387 															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1388 															m_texture->getTexture(), &texCoord[0], refParams,
1389 															lookupPrec, lodPrec,  m_context.getTestContext().getWatchDog());
1390 			}
1391 			if (numFailedPixels > 0)
1392 			{
1393 				m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1394 													<< TestLog::Image("ErrorMask", "Error mask", errorMask);
1395 			}
1396 			return numFailedPixels;
1397 		};
1398 
1399 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1400 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
1401 
1402 		int numFailedPixels = compareAndLogImages();
1403 
1404 		if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1405 		{
1406 			numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1407 		}
1408 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
1409 
1410 		if (numFailedPixels > 0)
1411 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1412 
1413 		{
1414 			const bool isOk = numFailedPixels == 0;
1415 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1416 		}
1417 	}
1418 }
1419 
1420 class TextureCubeMinLodTestInstance : public TextureCubeLodControlTestInstance
1421 {
1422 public:
TextureCubeMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1423 	TextureCubeMinLodTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1424 		: TextureCubeLodControlTestInstance(context, testParameters)
1425 	{
1426 	}
1427 
1428 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1429 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1430 	{
1431 		params.minLod = getMinLodForCell(cellNdx);
1432 	}
1433 };
1434 
1435 class TextureCubeMaxLodTestInstance : public TextureCubeLodControlTestInstance
1436 {
1437 public:
TextureCubeMaxLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1438 	TextureCubeMaxLodTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1439 		: TextureCubeLodControlTestInstance(context, testParameters)
1440 	{
1441 	}
1442 
1443 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1444 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1445 	{
1446 		params.maxLod = getMaxLodForCell(cellNdx);
1447 	}
1448 };
1449 
1450 class TextureCubeBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1451 {
1452 public:
TextureCubeBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1453 	TextureCubeBaseLevelTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1454 		: TextureCubeLodControlTestInstance(context, testParameters)
1455 		, m_testParam (testParameters)
1456 	{
1457 	}
1458 
1459 protected:
1460 	const TextureCubeMipmapTestCaseParameters m_testParam;
1461 
getBaseLevel(int cellNdx) const1462 	int getBaseLevel (int cellNdx) const
1463 	{
1464 		const int	numLevels	= deLog2Floor32(m_texSize)+1;
1465 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1466 
1467 		return baseLevel;
1468 	}
1469 
getReferenceParams(ReferenceParams & params,int cellNdx)1470 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1471 	{
1472 		params.baseLevel = getBaseLevel(cellNdx);
1473 	}
1474 };
1475 
1476 class TextureCubeMaxLevelTestInstance : public TextureCubeLodControlTestInstance
1477 {
1478 public:
TextureCubeMaxLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1479 	TextureCubeMaxLevelTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1480 		: TextureCubeLodControlTestInstance(context, testParameters)
1481 		, m_testParam (testParameters)
1482 	{
1483 	}
1484 
1485 protected:
1486 	const TextureCubeMipmapTestCaseParameters m_testParam;
getMaxLevel(int cellNdx) const1487 	int getMaxLevel (int cellNdx) const
1488 	{
1489 		const int	numLevels	= deLog2Floor32(m_texSize)+1;
1490 		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x974e21) % numLevels;
1491 
1492 		return maxLevel;
1493 	}
1494 
getReferenceParams(ReferenceParams & params,int cellNdx)1495 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1496 	{
1497 		params.maxLevel = getMaxLevel(cellNdx);
1498 	}
1499 };
1500 
1501 // Texture3DLodControlTestInstance
1502 class Texture3DLodControlTestInstance : public TestInstance
1503 {
1504 public:
1505 	typedef Texture3DMipmapTestCaseParameters	ParameterType;
1506 
1507 										Texture3DLodControlTestInstance		(Context& context, const ParameterType& testParameters);
1508 										~Texture3DLodControlTestInstance	(void);
1509 
1510 	virtual tcu::TestStatus				iterate								(void);
1511 
1512 protected:
1513 	virtual void						getReferenceParams					(ReferenceParams& params, int cellNdx)	= DE_NULL;
1514 
1515 	const int							m_texWidth;
1516 	const int							m_texHeight;
1517 	const int							m_texDepth;
1518 
1519 private:
1520 										Texture3DLodControlTestInstance		(const Texture3DLodControlTestInstance& other);
1521 	Texture3DLodControlTestInstance&	operator=							(const Texture3DLodControlTestInstance& other);
1522 
1523 	const ParameterType					m_testParameters;
1524 	tcu::Sampler::FilterMode			m_minFilter;
1525 	TestTexture3DSp						m_texture;
1526 	TextureRenderer						m_renderer;
1527 };
1528 
Texture3DLodControlTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1529 Texture3DLodControlTestInstance::Texture3DLodControlTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1530 	: TestInstance		(context)
1531 	, m_texWidth		(32)
1532 	, m_texHeight		(32)
1533 	, m_texDepth		(32)
1534 	, m_testParameters	(testParameters)
1535 	, m_minFilter		(testParameters.minFilter)
1536 	, m_texture			(DE_NULL)
1537 	, m_renderer		(context, testParameters.sampleCount, m_texWidth*4, m_texHeight*4, vk::makeComponentMappingRGBA(), testParameters.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD, testParameters.testType >= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD)
1538 {
1539 	const VkFormat			format		= VK_FORMAT_R8G8B8A8_UNORM;
1540 	tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(mapVkFormat(format));
1541 	const tcu::Vec4&		cScale		= fmtInfo.lookupScale;
1542 	const tcu::Vec4&		cBias		= fmtInfo.lookupBias;
1543 	const int				numLevels	= deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth))+1;
1544 
1545 	m_texture = TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(format), m_texWidth, m_texHeight, m_texDepth));
1546 
1547 	// Fill texture with colored grid.
1548 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1549 	{
1550 		const deUint32	step	= 0xff / (numLevels-1);
1551 		const deUint32	inc		= deClamp32(step*levelNdx, 0x00, 0xff);
1552 		const deUint32	dec		= 0xff - inc;
1553 		const deUint32	rgb		= (inc << 16) | (dec << 8) | 0xff;
1554 		const deUint32	color	= 0xff000000 | rgb;
1555 
1556 		tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec()*cScale + cBias);
1557 	}
1558 
1559 	m_renderer.add3DTexture(m_texture, testParameters.aspectMask);
1560 }
1561 
~Texture3DLodControlTestInstance(void)1562 Texture3DLodControlTestInstance::~Texture3DLodControlTestInstance (void)
1563 {
1564 }
1565 
iterate(void)1566 tcu::TestStatus Texture3DLodControlTestInstance::iterate (void)
1567 {
1568 	const tcu::Sampler::WrapMode	wrapS			= Sampler::CLAMP_TO_EDGE;
1569 	const tcu::Sampler::WrapMode	wrapT			= Sampler::CLAMP_TO_EDGE;
1570 	const tcu::Sampler::WrapMode	wrapR			= Sampler::CLAMP_TO_EDGE;
1571 	const tcu::Sampler::FilterMode	magFilter		= Sampler::NEAREST;
1572 
1573 	const tcu::Texture3D&			refTexture		= m_texture->getTexture();
1574 	const tcu::TextureFormat&		texFmt			= refTexture.getFormat();
1575 	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
1576 	const int						viewportWidth	= m_renderer.getRenderWidth();
1577 	const int						viewportHeight	= m_renderer.getRenderHeight();
1578 
1579 	tcu::Sampler					sampler			= util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1580 	ReferenceParams					refParams		(TEXTURETYPE_3D, sampler);
1581 	vector<float>					texCoord;
1582 	tcu::Surface					renderedFrame	(viewportWidth, viewportHeight);
1583 
1584 	// Viewport is divided into 4x4 grid.
1585 	const int						gridWidth		= 4;
1586 	const int						gridHeight		= 4;
1587 	const int						cellWidth		= viewportWidth / gridWidth;
1588 	const int						cellHeight		= viewportHeight / gridHeight;
1589 
1590 	// Sampling parameters.
1591 	refParams.sampler		= util::createSampler(wrapS, wrapT, wrapR, m_testParameters.minFilter, magFilter);
1592 	refParams.samplerType	= getSamplerType(texFmt);
1593 	refParams.colorBias		= fmtInfo.lookupBias;
1594 	refParams.colorScale	= fmtInfo.lookupScale;
1595 	refParams.maxLevel		= deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth));
1596 
1597 	// Render cells.
1598 	for (int gridY = 0; gridY < gridHeight; gridY++)
1599 	{
1600 		for (int gridX = 0; gridX < gridWidth; gridX++)
1601 		{
1602 			const int	curX		= cellWidth*gridX;
1603 			const int	curY		= cellHeight*gridY;
1604 			const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1605 			const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1606 			const int	cellNdx		= gridY*gridWidth + gridX;
1607 
1608 			// Compute texcoord.
1609 			getBasicTexCoord3D(texCoord, cellNdx);
1610 
1611 			getReferenceParams(refParams,cellNdx);
1612 			//Render
1613 			m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1614 			m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel, refParams.imageViewMinLod);
1615 			m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1616 		}
1617 	}
1618 
1619 	// Compare and log
1620 	{
1621 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1622 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1623 		const bool				isTrilinear		= m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1624 		tcu::LookupPrecision	lookupPrec;
1625 		tcu::LodPrecision		lodPrec;
1626 
1627 		lookupPrec.coordBits		= tcu::IVec3(20, 20, 20);
1628 		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
1629 		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1630 		lookupPrec.colorMask		= getCompareMask(pixelFormat);
1631 		lodPrec.derivateBits		= 10;
1632 		lodPrec.lodBits				= 8;
1633 
1634 		auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1635 		{
1636 			tcu::Surface			referenceFrame	(viewportWidth, viewportHeight);
1637 			tcu::Surface			errorMask		(viewportWidth, viewportHeight);
1638 			int						numFailedPixels = 0;
1639 
1640 			for (int gridY = 0; gridY < gridHeight; gridY++)
1641 			{
1642 				for (int gridX = 0; gridX < gridWidth; gridX++)
1643 				{
1644 					const int	curX		= cellWidth*gridX;
1645 					const int	curY		= cellHeight*gridY;
1646 					const int	curW		= gridX+1 == gridWidth ? (viewportWidth-curX) : cellWidth;
1647 					const int	curH		= gridY+1 == gridHeight ? (viewportHeight-curY) : cellHeight;
1648 					const int	cellNdx		= gridY*gridWidth + gridX;
1649 
1650 					getReferenceParams(refParams, cellNdx);
1651 
1652 					refParams.imageViewMinLodMode = imageViewLodMode;
1653 
1654 					// Compute texcoord.
1655 					if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
1656 						getBasicTexCoord3DImageViewMinlodIntTexCoord(texCoord);
1657 					else
1658 						getBasicTexCoord3D(texCoord, cellNdx);
1659 
1660 					// Render ideal result
1661 					sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
1662 								  refTexture, &texCoord[0], refParams);
1663 
1664 					// Compare this cell
1665 					numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1666 																tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1667 																tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
1668 																m_texture->getTexture(), &texCoord[0], refParams,
1669 																lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1670 				}
1671 			}
1672 			if (numFailedPixels > 0)
1673 			{
1674 				m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1675 													<< TestLog::Image("ErrorMask", "Error mask", errorMask);
1676 			}
1677 
1678 			return numFailedPixels;
1679 		};
1680 
1681 		m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1682 											<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
1683 
1684 		int numFailedPixels = compareAndLogImages();
1685 
1686 		if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1687 		{
1688 			numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1689 		}
1690 		m_context.getTestContext().getLog() << TestLog::EndImageSet;
1691 
1692 		if (numFailedPixels > 0)
1693 			m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1694 
1695 		{
1696 			const bool isOk = numFailedPixels == 0;
1697 			return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1698 		}
1699 	}
1700 }
1701 
1702 class Texture3DMinLodTestInstance : public Texture3DLodControlTestInstance
1703 {
1704 public:
Texture3DMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1705 	Texture3DMinLodTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1706 		: Texture3DLodControlTestInstance(context, testParameters)
1707 	{
1708 	}
1709 
1710 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1711 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1712 	{
1713 		params.minLod = getMinLodForCell(cellNdx);
1714 	}
1715 };
1716 
1717 class Texture3DMaxLodTestInstance : public Texture3DLodControlTestInstance
1718 {
1719 public:
Texture3DMaxLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1720 	Texture3DMaxLodTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1721 		: Texture3DLodControlTestInstance(context, testParameters)
1722 	{
1723 	}
1724 
1725 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1726 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1727 	{
1728 		params.maxLod = getMaxLodForCell(cellNdx);
1729 	}
1730 };
1731 
1732 class Texture3DBaseLevelTestInstance : public Texture3DLodControlTestInstance
1733 {
1734 public:
Texture3DBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1735 	Texture3DBaseLevelTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1736 		: Texture3DLodControlTestInstance(context, testParameters)
1737 		,m_testParam (testParameters)
1738 	{
1739 	}
1740 
1741 protected:
1742 	const Texture3DMipmapTestCaseParameters m_testParam;
1743 
getBaseLevel(int cellNdx) const1744 	int getBaseLevel (int cellNdx) const
1745 	{
1746 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
1747 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1748 
1749 		return baseLevel;
1750 	}
1751 
getReferenceParams(ReferenceParams & params,int cellNdx)1752 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1753 	{
1754 		params.baseLevel = getBaseLevel(cellNdx);
1755 	}
1756 };
1757 
1758 class Texture3DMaxLevelTestInstance : public Texture3DLodControlTestInstance
1759 {
1760 public:
Texture3DMaxLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1761 	Texture3DMaxLevelTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1762 		: Texture3DLodControlTestInstance(context, testParameters)
1763 		,m_testParam (testParameters)
1764 	{
1765 	}
1766 
1767 protected:
1768 	const Texture3DMipmapTestCaseParameters m_testParam;
1769 
getMaxLevel(int cellNdx) const1770 	int getMaxLevel (int cellNdx) const
1771 	{
1772 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
1773 		const int	maxLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x9111e7) % numLevels;
1774 
1775 		return maxLevel;
1776 	}
1777 
getReferenceParams(ReferenceParams & params,int cellNdx)1778 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1779 	{
1780 		params.maxLevel = getMaxLevel(cellNdx);
1781 	}
1782 };
1783 
1784 #ifndef CTS_USES_VULKANSC
1785 
1786 class Texture2DImageViewMinLodTestInstance : public Texture2DLodControlTestInstance
1787 {
1788 public:
Texture2DImageViewMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1789 	Texture2DImageViewMinLodTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1790 		: Texture2DLodControlTestInstance(context, testParameters)
1791 	{
1792 	}
1793 
1794 protected:
1795 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1796 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1797 	{
1798 		de::Random rnd(cellNdx + 1);
1799 
1800 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1801 		float minBaseLevel = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1802 		return rnd.getFloat(minBaseLevel, (float)maxLevel);
1803 	}
1804 
getReferenceParams(ReferenceParams & params,int cellNdx)1805 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1806 	{
1807 		params.minLod = getMinLodForCell(cellNdx);
1808 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1809 	}
1810 };
1811 
1812 class Texture2DImageViewMinLodBaseLevelTestInstance : public Texture2DLodControlTestInstance
1813 {
1814 public:
Texture2DImageViewMinLodBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1815 	Texture2DImageViewMinLodBaseLevelTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1816 		: Texture2DLodControlTestInstance(context, testParameters)
1817 		, m_testParam (testParameters)
1818 	{
1819 	}
1820 
1821 protected:
1822 	const Texture2DMipmapTestCaseParameters m_testParam;
1823 
getBaseLevel(int cellNdx) const1824 	int getBaseLevel (int cellNdx) const
1825 	{
1826 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
1827 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1828 
1829 		return baseLevel;
1830 	}
1831 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1832 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1833 	{
1834 		de::Random rnd(cellNdx + 1);
1835 
1836 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1837 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1838 		return rnd.getFloat(minValue, (float)maxLevel);
1839 	}
1840 
getReferenceParams(ReferenceParams & params,int cellNdx)1841 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1842 	{
1843 		params.baseLevel = getBaseLevel(cellNdx);
1844 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1845 	}
1846 };
1847 
1848 class Texture3DImageViewMinLodTestInstance : public Texture3DLodControlTestInstance
1849 {
1850 public:
Texture3DImageViewMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1851 	Texture3DImageViewMinLodTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1852 		: Texture3DLodControlTestInstance(context, testParameters)
1853 	{
1854 	}
1855 
1856 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1857 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1858 	{
1859 		de::Random rnd(cellNdx + 1);
1860 
1861 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1862 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1863 		return rnd.getFloat(minValue, (float)maxLevel);
1864 	}
1865 
getReferenceParams(ReferenceParams & params,int cellNdx)1866 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1867 	{
1868 		params.minLod = getMinLodForCell(cellNdx);
1869 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1870 	}
1871 };
1872 
1873 class Texture3DImageViewMinLodBaseLevelTestInstance : public Texture3DLodControlTestInstance
1874 {
1875 public:
Texture3DImageViewMinLodBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1876 	Texture3DImageViewMinLodBaseLevelTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
1877 		: Texture3DLodControlTestInstance(context, testParameters)
1878 		, m_testParam (testParameters)
1879 	{
1880 	}
1881 
1882 protected:
1883 	const Texture3DMipmapTestCaseParameters m_testParam;
1884 
getBaseLevel(int cellNdx) const1885 	int getBaseLevel (int cellNdx) const
1886 	{
1887 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
1888 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1889 
1890 		return baseLevel;
1891 	}
1892 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1893 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1894 	{
1895 		de::Random rnd(cellNdx + 1);
1896 
1897 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1898 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1899 		return rnd.getFloat(minValue, (float)maxLevel);
1900 	}
1901 
getReferenceParams(ReferenceParams & params,int cellNdx)1902 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1903 	{
1904 		params.baseLevel = getBaseLevel(cellNdx);
1905 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1906 
1907 	}
1908 };
1909 
1910 class TextureCubeImageViewMinLodTestInstance : public TextureCubeLodControlTestInstance
1911 {
1912 public:
TextureCubeImageViewMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1913 	TextureCubeImageViewMinLodTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1914 		: TextureCubeLodControlTestInstance(context, testParameters)
1915 	{
1916 	}
1917 
1918 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1919 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1920 	{
1921 		de::Random rnd(cellNdx + 1);
1922 
1923 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1924 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1925 		return rnd.getFloat(minValue, (float)maxLevel);
1926 	}
1927 
getReferenceParams(ReferenceParams & params,int cellNdx)1928 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1929 	{
1930 		params.minLod = getMinLodForCell(cellNdx);
1931 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1932 	}
1933 };
1934 
1935 class TextureCubeImageViewMinLodBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1936 {
1937 public:
TextureCubeImageViewMinLodBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1938 	TextureCubeImageViewMinLodBaseLevelTestInstance (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
1939 		: TextureCubeLodControlTestInstance(context, testParameters)
1940 		, m_testParam (testParameters)
1941 	{
1942 	}
1943 
1944 protected:
1945 	const TextureCubeMipmapTestCaseParameters m_testParam;
1946 
getBaseLevel(int cellNdx) const1947 	int getBaseLevel (int cellNdx) const
1948 	{
1949 		const int	numLevels	= deLog2Floor32(m_texSize)+1;
1950 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1951 
1952 		return baseLevel;
1953 	}
1954 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1955 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1956 	{
1957 		de::Random rnd(cellNdx + 1);
1958 
1959 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1960 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1961 		return rnd.getFloat(minValue, (float)maxLevel);
1962 	}
1963 
getReferenceParams(ReferenceParams & params,int cellNdx)1964 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1965 	{
1966 		params.baseLevel = getBaseLevel(cellNdx);
1967 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1968 	}
1969 };
1970 
1971 class Texture2DImageViewMinLodIntTexCoordTestInstance : public Texture2DLodControlTestInstance
1972 {
1973 public:
Texture2DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1974 	Texture2DImageViewMinLodIntTexCoordTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
1975 		: Texture2DLodControlTestInstance(context, testParameters)
1976 		, m_testParam (testParameters)
1977 	{
1978 	}
1979 
1980 protected:
1981 	const Texture2DMipmapTestCaseParameters m_testParam;
1982 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1983 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
1984 	{
1985 		de::Random rnd(cellNdx + 1);
1986 
1987 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1988 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1989 		return rnd.getFloat(minValue, (float)maxLevel);
1990 	}
1991 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const1992 	int getLodTexelFetch (int cellNdx, int baseLevel, int maxLevel) const
1993 	{
1994 		de::Random rnd(cellNdx + 1);
1995 		return rnd.getInt(baseLevel, maxLevel) - baseLevel;
1996 	}
1997 
getReferenceParams(ReferenceParams & params,int cellNdx)1998 	void getReferenceParams (ReferenceParams& params, int cellNdx)
1999 	{
2000 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2001 		params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2002 		params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2003 	}
2004 };
2005 
2006 class Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture2DLodControlTestInstance
2007 {
2008 public:
Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2009 	Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
2010 		: Texture2DLodControlTestInstance(context, testParameters)
2011 		, m_testParam (testParameters)
2012 	{
2013 	}
2014 
2015 protected:
2016 	const Texture2DMipmapTestCaseParameters m_testParam;
2017 
getBaseLevel(int cellNdx) const2018 	int getBaseLevel (int cellNdx) const
2019 	{
2020 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, m_texHeight))+1;
2021 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
2022 
2023 		return baseLevel;
2024 	}
2025 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2026 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
2027 	{
2028 		de::Random rnd(cellNdx + 1);
2029 
2030 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2031 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2032 		return rnd.getFloat(minValue, (float)maxLevel);
2033 	}
2034 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2035 	int getLodTexelFetch (int cellNdx, int baseLevel, int maxLevel) const
2036 	{
2037 		de::Random rnd(cellNdx + 1);
2038 		return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2039 	}
2040 
getReferenceParams(ReferenceParams & params,int cellNdx)2041 	void getReferenceParams (ReferenceParams& params, int cellNdx)
2042 	{
2043 		params.baseLevel = getBaseLevel(cellNdx);
2044 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2045 		params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2046 		params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2047 	}
2048 };
2049 
2050 class Texture2DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2051 {
2052 public:
2053 	Texture2DImageViewMinLodIntTexCoordTest						(tcu::TestContext&							testContext,
2054 																 const string&								name,
2055 																 const Texture2DMipmapTestCaseParameters&	params);
2056 	~Texture2DImageViewMinLodIntTexCoordTest					(void);
2057 	void						initPrograms					(SourceCollections& sourceCollections) const;
2058 	TestInstance*				createInstance					(Context& context) const;
2059 	void						checkSupport					(Context& context) const;
2060 
2061 protected:
2062 	const Texture2DMipmapTestCaseParameters	m_params;
2063 };
2064 
Texture2DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const Texture2DMipmapTestCaseParameters & params)2065 Texture2DImageViewMinLodIntTexCoordTest::Texture2DImageViewMinLodIntTexCoordTest (tcu::TestContext&							testContext,
2066 																				  const string&								name,
2067 																				  const Texture2DMipmapTestCaseParameters&	params)
2068 	: vkt::TestCase	(testContext, name)
2069 	, m_params		(params)
2070 {
2071 }
2072 
~Texture2DImageViewMinLodIntTexCoordTest(void)2073 Texture2DImageViewMinLodIntTexCoordTest::~Texture2DImageViewMinLodIntTexCoordTest (void)
2074 {
2075 }
2076 
initPrograms(SourceCollections & sourceCollections) const2077 void Texture2DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections& sourceCollections) const
2078 {
2079 	static const char* vertShader =
2080 		"#version 450\n"
2081 		"layout(location = 0) in vec4 a_position;\n"
2082 		"layout(location = 1) in vec2 a_texCoord;\n"
2083 		"out gl_PerVertex { vec4 gl_Position; };\n"
2084 		"\n"
2085 		"void main (void)\n"
2086 		"{\n"
2087 		"	gl_Position = a_position;\n"
2088 		"}\n";
2089 
2090 	static const char* fragShader =
2091 		"#version 450\n"
2092 		"layout(location = 0) out vec4 outColor;\n"
2093 		"layout (set=0, binding=0, std140) uniform Block \n"
2094 		"{\n"
2095 		"  float u_bias;\n"
2096 		"  float u_ref;\n"
2097 		"  vec4 u_colorScale;\n"
2098 		"  vec4 u_colorBias;\n"
2099 		"  int u_lod;\n"
2100 		"};\n\n"
2101 		"layout (set=1, binding=0) uniform sampler2D u_sampler;\n"
2102 		"void main (void)\n"
2103 		"{\n"
2104 		"  ivec2 texCoord = ivec2(0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2105 		"  outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2106 		"}\n";
2107 	sourceCollections.glslSources.add("vertex_2D_FETCH_LOD") << glu::VertexSource(vertShader);
2108 	sourceCollections.glslSources.add("fragment_2D_FETCH_LOD") << glu::FragmentSource(fragShader);
2109 }
2110 
checkSupport(Context & context) const2111 void Texture2DImageViewMinLodIntTexCoordTest::checkSupport(Context& context) const
2112 {
2113 	DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2114 
2115 	context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2116 	context.requireDeviceFunctionality("VK_EXT_robustness2");
2117 	vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2118 	imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2119 	imageViewMinLodFeatures.pNext = DE_NULL;
2120 
2121 	VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2122 	robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2123 	robustness2Features.pNext = &imageViewMinLodFeatures;
2124 	vk::VkPhysicalDeviceFeatures2 features2;
2125 
2126 	features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2127 	features2.pNext = &robustness2Features;
2128 
2129 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2130 
2131 	if (imageViewMinLodFeatures.minLod == DE_FALSE)
2132 		TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2133 
2134 	if (robustness2Features.robustImageAccess2 == DE_FALSE)
2135 		TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2136 }
2137 
createInstance(Context & context) const2138 TestInstance* Texture2DImageViewMinLodIntTexCoordTest::createInstance(Context& context) const
2139 {
2140 	if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2141 		return new Texture2DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2142 	else
2143 		return new Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2144 }
2145 
2146 class Texture3DImageViewMinLodIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2147 {
2148 public:
Texture3DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2149 	Texture3DImageViewMinLodIntTexCoordTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
2150 		: Texture3DLodControlTestInstance(context, testParameters)
2151 		, m_testParam (testParameters)
2152 	{
2153 	}
2154 
2155 protected:
2156 	const Texture3DMipmapTestCaseParameters m_testParam;
2157 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2158 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
2159 	{
2160 		de::Random rnd(cellNdx + 1);
2161 
2162 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2163 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2164 		return rnd.getFloat(minValue, (float)maxLevel);
2165 	}
2166 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2167 	int getLodTexelFetch (int cellNdx, int baseLevel, int maxLevel) const
2168 	{
2169 		de::Random rnd(cellNdx + 1);
2170 		return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2171 	}
2172 
getReferenceParams(ReferenceParams & params,int cellNdx)2173 	void getReferenceParams (ReferenceParams& params, int cellNdx)
2174 	{
2175 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2176 		params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2177 		params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2178 	}
2179 };
2180 
2181 class Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2182 {
2183 public:
Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2184 	Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
2185 		: Texture3DLodControlTestInstance(context, testParameters)
2186 		, m_testParam (testParameters)
2187 	{
2188 	}
2189 
2190 protected:
2191 	const Texture3DMipmapTestCaseParameters m_testParam;
2192 
getBaseLevel(int cellNdx) const2193 	int getBaseLevel (int cellNdx) const
2194 	{
2195 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
2196 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
2197 
2198 		return baseLevel;
2199 	}
2200 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2201 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
2202 	{
2203 		de::Random rnd(cellNdx + 1);
2204 
2205 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2206 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2207 		return rnd.getFloat(minValue, (float)maxLevel);
2208 	}
2209 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2210 	int getLodTexelFetch (int cellNdx, int baseLevel, int maxLevel) const
2211 	{
2212 		de::Random rnd(cellNdx + 1);
2213 		return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2214 	}
2215 
getReferenceParams(ReferenceParams & params,int cellNdx)2216 	void getReferenceParams (ReferenceParams& params, int cellNdx)
2217 	{
2218 		params.baseLevel = getBaseLevel(cellNdx);
2219 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2220 		params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2221 		params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2222 	}
2223 };
2224 
2225 class Texture3DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2226 {
2227 public:
2228 	Texture3DImageViewMinLodIntTexCoordTest						(tcu::TestContext&							testContext,
2229 																 const string&								name,
2230 																 const Texture3DMipmapTestCaseParameters&	params);
2231 	~Texture3DImageViewMinLodIntTexCoordTest					(void);
2232 	void						initPrograms					(SourceCollections& sourceCollections) const;
2233 	TestInstance*				createInstance					(Context& context) const;
2234 	void						checkSupport					(Context& context) const;
2235 
2236 protected:
2237 	const Texture3DMipmapTestCaseParameters	m_params;
2238 };
2239 
Texture3DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const Texture3DMipmapTestCaseParameters & params)2240 Texture3DImageViewMinLodIntTexCoordTest::Texture3DImageViewMinLodIntTexCoordTest (tcu::TestContext&							testContext,
2241 																				  const string&								name,
2242 																				  const Texture3DMipmapTestCaseParameters&	params)
2243 	: vkt::TestCase	(testContext, name)
2244 	, m_params		(params)
2245 {
2246 }
2247 
~Texture3DImageViewMinLodIntTexCoordTest(void)2248 Texture3DImageViewMinLodIntTexCoordTest::~Texture3DImageViewMinLodIntTexCoordTest (void)
2249 {
2250 }
2251 
initPrograms(SourceCollections & sourceCollections) const2252 void Texture3DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections& sourceCollections) const
2253 {
2254 	static const char* vertShader =
2255 		"#version 450\n"
2256 		"layout(location = 0) in vec4 a_position;\n"
2257 		"layout(location = 1) in vec3 a_texCoord;\n"
2258 		"out gl_PerVertex { vec4 gl_Position; };\n"
2259 		"\n"
2260 		"void main (void)\n"
2261 		"{\n"
2262 		"	gl_Position = a_position;\n"
2263 		"}\n";
2264 
2265 	static const char* fragShader =
2266 		"#version 450\n"
2267 		"layout(location = 0) out vec4 outColor;\n"
2268 		"layout (set=0, binding=0, std140) uniform Block \n"
2269 		"{\n"
2270 		"  float u_bias;\n"
2271 		"  float u_ref;\n"
2272 		"  vec4 u_colorScale;\n"
2273 		"  vec4 u_colorBias;\n"
2274 		"  int u_lod;\n"
2275 		"};\n\n"
2276 		"layout (set=1, binding=0) uniform sampler3D u_sampler;\n"
2277 		"void main (void)\n"
2278 		"{\n"
2279 		"  ivec3 texCoord = ivec3(0,0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2280 		"  outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2281 		"}\n";
2282 	sourceCollections.glslSources.add("vertex_3D_FETCH_LOD") << glu::VertexSource(vertShader);
2283 	sourceCollections.glslSources.add("fragment_3D_FETCH_LOD") << glu::FragmentSource(fragShader);
2284 }
2285 
checkSupport(Context & context) const2286 void Texture3DImageViewMinLodIntTexCoordTest::checkSupport(Context& context) const
2287 {
2288 	DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2289 
2290 	context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2291 	context.requireDeviceFunctionality("VK_EXT_robustness2");
2292 	vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2293 	imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2294 	imageViewMinLodFeatures.pNext = DE_NULL;
2295 
2296 	VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2297 	robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2298 	robustness2Features.pNext = &imageViewMinLodFeatures;
2299 	vk::VkPhysicalDeviceFeatures2 features2;
2300 
2301 	features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2302 	features2.pNext = &robustness2Features;
2303 
2304 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2305 
2306 	if (imageViewMinLodFeatures.minLod == DE_FALSE)
2307 		TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2308 
2309 	if (robustness2Features.robustImageAccess2 == DE_FALSE)
2310 		TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2311 }
2312 
createInstance(Context & context) const2313 TestInstance* Texture3DImageViewMinLodIntTexCoordTest::createInstance(Context& context) const
2314 {
2315 	if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2316 		return new Texture3DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2317 	else
2318 	   return new Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2319 }
2320 
2321 // Texture gather tests.
2322 enum class GatherMinLod
2323 {
2324 	MINLOD_0_1,		// 0.1
2325 	MINLOD_1_1,		// 1.1
2326 };
2327 
2328 struct GatherParams
2329 {
2330 	uint32_t		randomSeed;	// Seed for the pseudorandom number generator.
2331 	GatherMinLod	minLod;		// Idea: make it 0.1 or 1.1
2332 	int				component;	// 0, 1, 2, 3 for the gather operation.
2333 
getNumericMinLodvkt::texture::__anonf7de2b9d0111::GatherParams2334 	float getNumericMinLod (void) const
2335 	{
2336 		float lod = 0.0f;
2337 
2338 		switch (minLod)
2339 		{
2340 		case GatherMinLod::MINLOD_0_1:	lod = 0.1f; break;
2341 		case GatherMinLod::MINLOD_1_1:	lod = 1.1f; break;
2342 		default: DE_ASSERT(false); break;
2343 		}
2344 
2345 		return lod;
2346 	}
2347 
getMinLodIntegervkt::texture::__anonf7de2b9d0111::GatherParams2348 	uint32_t getMinLodInteger (void) const
2349 	{
2350 		uint32_t lod = 0u;
2351 
2352 		switch (minLod)
2353 		{
2354 		case GatherMinLod::MINLOD_0_1:	lod = 0u; break;
2355 		case GatherMinLod::MINLOD_1_1:	lod = 1u; break;
2356 		default: DE_ASSERT(false); break;
2357 		}
2358 
2359 		return lod;
2360 	}
2361 
needsRobustness2vkt::texture::__anonf7de2b9d0111::GatherParams2362 	bool needsRobustness2 (void) const
2363 	{
2364 		return (getNumericMinLod() >= 1.0f);
2365 	}
2366 };
2367 
2368 class TextureGatherMinLodTest : public vkt::TestCase
2369 {
2370 public:
TextureGatherMinLodTest(tcu::TestContext & testCtx,const std::string & name,const GatherParams & params)2371 					TextureGatherMinLodTest		(tcu::TestContext& testCtx, const std::string& name, const GatherParams& params)
2372 						: vkt::TestCase	(testCtx, name)
2373 						, m_params		(params)
2374 						{}
~TextureGatherMinLodTest(void)2375 	virtual			~TextureGatherMinLodTest	(void) {}
2376 
2377 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
2378 	TestInstance*	createInstance				(Context& context) const override;
2379 	void			checkSupport				(Context& context) const override;
2380 
2381 protected:
2382 	GatherParams	m_params;
2383 };
2384 
2385 class TextureGatherMinLodInstance : public vkt::TestInstance
2386 {
2387 public:
TextureGatherMinLodInstance(Context & context,const GatherParams & params)2388 					TextureGatherMinLodInstance		(Context& context, const GatherParams& params)
2389 						: vkt::TestInstance	(context)
2390 						, m_params			(params)
2391 						{}
~TextureGatherMinLodInstance(void)2392 	virtual			~TextureGatherMinLodInstance	(void) {}
2393 
2394 	tcu::TestStatus	iterate							(void) override;
2395 
2396 protected:
2397 	GatherParams	m_params;
2398 };
2399 
2400 // Test idea: create texture with 3 levels, each of them having a unique nonzero color. Render gathering the color from a fixed
2401 // position in that texture (center point). Use the minLod parameter when creating the view to control which one should be the
2402 // output color. If minLod is 0.1, minLodInteger should be 0 and gathering from the base level is defined, so we should get the
2403 // output color from the base level. If minLod is 1.1, gathering texels from the base level requires robustness2 and will result in
2404 // zeros instead of the color from levels 0 or 1.
initPrograms(vk::SourceCollections & programCollection) const2405 void TextureGatherMinLodTest::initPrograms (vk::SourceCollections &programCollection) const
2406 {
2407 	// Full screen triangle covering the whole viewport.
2408 	std::ostringstream vert;
2409 	vert
2410 		<< "#version 450\n"
2411 		<< "\n"
2412 		<< "vec2 positions[3] = vec2[](\n"
2413 		<< "    vec2(-1.0, -1.0),\n"
2414 		<< "    vec2(3.0, -1.0),\n"
2415 		<< "    vec2(-1.0, 3.0)\n"
2416 		<< ");\n"
2417 		<< "\n"
2418 		<< "void main (void)\n"
2419 		<< "{\n"
2420 		<< "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
2421 		<< "}\n"
2422 		;
2423 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2424 
2425 	std::ostringstream frag;
2426 	frag
2427 		<< "#version 450\n"
2428 		<< "\n"
2429 		<< "layout (location=0) out vec4 outColor;\n"
2430 		<< "layout (set=0, binding=0) uniform sampler2D u_sampler;\n"
2431 		<< "\n"
2432 		<< "void main (void)\n"
2433 		<< "{\n"
2434 		<< "    const vec2 gatherCoords = vec2(0.5, 0.5);\n"
2435 		<< "    const vec4 gatherRes = textureGather(u_sampler, gatherCoords, " << m_params.component << ");\n"
2436 		<< "    outColor = vec4(gatherRes.xyz, 1.0);\n"
2437 		<< "}\n";
2438 		;
2439 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2440 }
2441 
checkSupport(Context & context) const2442 void TextureGatherMinLodTest::checkSupport (Context& context) const
2443 {
2444 	context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2445 	context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2446 
2447 	if (m_params.needsRobustness2())
2448 	{
2449 		context.requireDeviceFunctionality("VK_EXT_robustness2");
2450 
2451 		VkPhysicalDeviceRobustness2FeaturesEXT	robustness2Features	= initVulkanStructure();
2452 		VkPhysicalDeviceFeatures2				features2			= initVulkanStructure(&robustness2Features);
2453 
2454 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2455 
2456 		if (robustness2Features.robustImageAccess2 == DE_FALSE)
2457 			TCU_THROW(NotSupportedError, "robustImageAccess2 not supported");
2458 	}
2459 }
2460 
createInstance(Context & context) const2461 TestInstance* TextureGatherMinLodTest::createInstance (Context& context) const
2462 {
2463 	return new TextureGatherMinLodInstance(context, m_params);
2464 }
2465 
2466 // Device helper: this is needed because we sometimes need a custom device with robustImageAccess2.
2467 class DeviceHelper
2468 {
2469 public:
~DeviceHelper()2470 	virtual ~DeviceHelper () {}
2471 	virtual const DeviceInterface&	getDeviceInterface	(void) const = 0;
2472 	virtual VkDevice				getDevice			(void) const = 0;
2473 	virtual uint32_t				getQueueFamilyIndex	(void) const = 0;
2474 	virtual VkQueue					getQueue			(void) const = 0;
2475 	virtual Allocator&				getAllocator		(void) const = 0;
2476 };
2477 
2478 // This one just reuses the default device from the context.
2479 class ContextDeviceHelper : public DeviceHelper
2480 {
2481 public:
ContextDeviceHelper(Context & context)2482 	ContextDeviceHelper (Context& context)
2483 		: m_deviceInterface		(context.getDeviceInterface())
2484 		, m_device				(context.getDevice())
2485 		, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
2486 		, m_queue				(context.getUniversalQueue())
2487 		, m_allocator			(context.getDefaultAllocator())
2488 		{}
2489 
~ContextDeviceHelper()2490 	virtual ~ContextDeviceHelper () {}
2491 
getDeviceInterface(void) const2492 	const DeviceInterface&	getDeviceInterface	(void) const override	{ return m_deviceInterface;		}
getDevice(void) const2493 	VkDevice				getDevice			(void) const override	{ return m_device;				}
getQueueFamilyIndex(void) const2494 	uint32_t				getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const2495 	VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const2496 	Allocator&				getAllocator		(void) const override	{ return m_allocator;			}
2497 
2498 protected:
2499 	const DeviceInterface&	m_deviceInterface;
2500 	const VkDevice			m_device;
2501 	const uint32_t			m_queueFamilyIndex;
2502 	const VkQueue			m_queue;
2503 	Allocator&				m_allocator;
2504 };
2505 
2506 // This one creates a new device with robustImageAccess2.
2507 class RobustImageAccess2DeviceHelper : public DeviceHelper
2508 {
2509 public:
RobustImageAccess2DeviceHelper(Context & context)2510 	RobustImageAccess2DeviceHelper (Context& context)
2511 	{
2512 		const auto&	vkp				= context.getPlatformInterface();
2513 		const auto&	vki				= context.getInstanceInterface();
2514 		const auto	instance		= context.getInstance();
2515 		const auto	physicalDevice	= context.getPhysicalDevice();
2516 		const auto	queuePriority	= 1.0f;
2517 
2518 		// Queue index first.
2519 		m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2520 
2521 		// Create a universal queue that supports graphics and compute.
2522 		const VkDeviceQueueCreateInfo queueParams =
2523 		{
2524 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
2525 			DE_NULL,									// const void*					pNext;
2526 			0u,											// VkDeviceQueueCreateFlags		flags;
2527 			m_queueFamilyIndex,							// deUint32						queueFamilyIndex;
2528 			1u,											// deUint32						queueCount;
2529 			&queuePriority								// const float*					pQueuePriorities;
2530 		};
2531 
2532 		const char* extensions[] =
2533 		{
2534 			"VK_EXT_robustness2",
2535 		};
2536 
2537 		VkPhysicalDeviceImageViewMinLodFeaturesEXT	minLodfeatures		= initVulkanStructure();
2538 		VkPhysicalDeviceRobustness2FeaturesEXT		robustness2Features	= initVulkanStructure(&minLodfeatures);
2539 		VkPhysicalDeviceFeatures2					features2			= initVulkanStructure(&robustness2Features);
2540 
2541 		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
2542 
2543 		const VkDeviceCreateInfo deviceCreateInfo =
2544 		{
2545 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,					//sType;
2546 			&features2,												//pNext;
2547 			0u,														//flags
2548 			1u,														//queueRecordCount;
2549 			&queueParams,											//pRequestedQueues;
2550 			0u,														//layerCount;
2551 			nullptr,												//ppEnabledLayerNames;
2552 			static_cast<uint32_t>(de::arrayLength(extensions)),		// deUint32							enabledExtensionCount;
2553 			extensions,												// const char* const*				ppEnabledExtensionNames;
2554 			nullptr,												//pEnabledFeatures;
2555 		};
2556 
2557 		m_device	= createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
2558 		m_vkd		.reset(new DeviceDriver(vkp, instance, m_device.get(), context.getUsedApiVersion()));
2559 		m_queue		= getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
2560 		m_allocator	.reset(new SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
2561 	}
2562 
~RobustImageAccess2DeviceHelper()2563 	virtual ~RobustImageAccess2DeviceHelper () {}
2564 
getDeviceInterface(void) const2565 	const DeviceInterface&	getDeviceInterface	(void) const override	{ return *m_vkd;				}
getDevice(void) const2566 	VkDevice				getDevice			(void) const override	{ return m_device.get();		}
getQueueFamilyIndex(void) const2567 	uint32_t				getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const2568 	VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const2569 	Allocator&				getAllocator		(void) const override	{ return *m_allocator;			}
2570 
2571 protected:
2572 	Move<VkDevice>						m_device;
2573 	std::unique_ptr<DeviceDriver>		m_vkd;
2574 	deUint32							m_queueFamilyIndex;
2575 	VkQueue								m_queue;
2576 	std::unique_ptr<SimpleAllocator>	m_allocator;
2577 };
2578 
2579 std::unique_ptr<DeviceHelper> g_robustness2DeviceHelper;
2580 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
2581 
getDeviceHelper(Context & context,bool needsRobustness2)2582 DeviceHelper& getDeviceHelper (Context& context, bool needsRobustness2)
2583 {
2584 	if (needsRobustness2)
2585 	{
2586 		if (!g_robustness2DeviceHelper)
2587 			g_robustness2DeviceHelper.reset(new RobustImageAccess2DeviceHelper(context));
2588 		return *g_robustness2DeviceHelper;
2589 	}
2590 
2591 	if (!g_contextDeviceHelper)
2592 		g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
2593 	return *g_contextDeviceHelper;
2594 }
2595 
2596 // Cleanup function for the test group.
destroyDeviceHelpers(tcu::TestCaseGroup *)2597 void destroyDeviceHelpers (tcu::TestCaseGroup*)
2598 {
2599 	g_robustness2DeviceHelper.reset(nullptr);
2600 	g_contextDeviceHelper.reset(nullptr);
2601 }
2602 
iterate(void)2603 tcu::TestStatus TextureGatherMinLodInstance::iterate (void)
2604 {
2605 	const auto&	deviceHelper	= getDeviceHelper(m_context, m_params.needsRobustness2());
2606 	const auto&	vkd				= deviceHelper.getDeviceInterface();
2607 	const auto	device			= deviceHelper.getDevice();
2608 	const auto	queueIndex		= deviceHelper.getQueueFamilyIndex();
2609 	const auto	queue			= deviceHelper.getQueue();
2610 	auto&		alloc			= deviceHelper.getAllocator();
2611 
2612 	const auto			imageFormat		= VK_FORMAT_R8G8B8A8_UNORM;
2613 	const auto			tcuFormat		= mapVkFormat(imageFormat);
2614 	const auto			colorExtent		= makeExtent3D(1u, 1u, 1u);
2615 	const tcu::IVec3	iColorExtent	(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth));
2616 	const auto			texExtent		= makeExtent3D(8u, 8u, 1u);
2617 	const auto			texMipLevels	= 3u;
2618 	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2619 	const auto			texUsage		= (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2620 	const auto			minLodF			= m_params.getNumericMinLod();
2621 	const auto			minLodU			= m_params.getMinLodInteger();
2622 	const tcu::Vec4		clearColor		(0.0f, 0.0f, 0.0f, 1.0f);
2623 
2624 	// Color attachment: a simple 1x1 image.
2625 	const VkImageCreateInfo colorCreateInfo =
2626 	{
2627 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2628 		nullptr,								//	const void*				pNext;
2629 		0u,										//	VkImageCreateFlags		flags;
2630 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2631 		imageFormat,							//	VkFormat				format;
2632 		colorExtent,							//	VkExtent3D				extent;
2633 		1u,										//	uint32_t				mipLevels;
2634 		1u,										//	uint32_t				arrayLayers;
2635 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2636 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2637 		colorUsage,								//	VkImageUsageFlags		usage;
2638 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2639 		0u,										//	uint32_t				queueFamilyIndexCount;
2640 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2641 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2642 	};
2643 
2644 	ImageWithMemory	colorBuffer		(vkd, device, alloc, colorCreateInfo, MemoryRequirement::Any);
2645 	const auto		colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2646 	const auto		colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2647 	const auto		colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2648 
2649 	// Texture: an 8x8 image with several mip levels.
2650 	const VkImageCreateInfo texCreateInfo =
2651 	{
2652 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2653 		nullptr,								//	const void*				pNext;
2654 		0u,										//	VkImageCreateFlags		flags;
2655 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2656 		imageFormat,							//	VkFormat				format;
2657 		texExtent,								//	VkExtent3D				extent;
2658 		texMipLevels,							//	uint32_t				mipLevels;
2659 		1u,										//	uint32_t				arrayLayers;
2660 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2661 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2662 		texUsage,								//	VkImageUsageFlags		usage;
2663 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2664 		0u,										//	uint32_t				queueFamilyIndexCount;
2665 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2666 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2667 	};
2668 
2669 	ImageWithMemory texture (vkd, device, alloc, texCreateInfo, MemoryRequirement::Any);
2670 	const auto texSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texMipLevels, 0u, 1u);
2671 
2672 	DE_ASSERT(texMipLevels > 0u);
2673 	DE_ASSERT(minLodU < texMipLevels);
2674 
2675 	const VkImageViewMinLodCreateInfoEXT texMinLodInfo =
2676 	{
2677 		VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT,	//	VkStructureType	sType;
2678 		nullptr,												//	const void*		pNext;
2679 		minLodF,												//	float			minLod;
2680 	};
2681 
2682 	const VkImageViewCreateInfo texViewCreateInfo =
2683 	{
2684 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	//	VkStructureType			sType;
2685 		&texMinLodInfo,								//	const void*				pNext;
2686 		0u,											//	VkImageViewCreateFlags	flags;
2687 		texture.get(),								//	VkImage					image;
2688 		VK_IMAGE_VIEW_TYPE_2D,						//	VkImageViewType			viewType;
2689 		imageFormat,								//	VkFormat				format;
2690 		makeComponentMappingRGBA(),					//	VkComponentMapping		components;
2691 		texSRR,										//	VkImageSubresourceRange	subresourceRange;
2692 	};
2693 
2694 	const auto texView = createImageView(vkd, device, &texViewCreateInfo);
2695 
2696 	// Verification buffer for the color attachment.
2697 	const auto			verifBufferSize			= static_cast<VkDeviceSize>(iColorExtent.x() * iColorExtent.y() * iColorExtent.z() * tcu::getPixelSize(tcuFormat));
2698 	const auto			verifBufferCreateInfo	= makeBufferCreateInfo(verifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2699 	BufferWithMemory	verifBuffer				(vkd, device, alloc, verifBufferCreateInfo, MemoryRequirement::HostVisible);
2700 	auto&				verifBufferAlloc		= verifBuffer.getAllocation();
2701 	void*				verifBufferData			= verifBufferAlloc.getHostPtr();
2702 
2703 	// Descriptor set layout.
2704 	DescriptorSetLayoutBuilder setLayoutBuilder;
2705 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
2706 	const auto setLayout = setLayoutBuilder.build(vkd, device);
2707 
2708 	// Pipeline layout.
2709 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
2710 
2711 	// Sampler.
2712 	const VkSamplerCreateInfo samplerCreateInfo =
2713 	{
2714 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		//	VkStructureType			sType;
2715 		nullptr,									//	const void*				pNext;
2716 		0u,											//	VkSamplerCreateFlags	flags;
2717 		VK_FILTER_LINEAR,							//	VkFilter				magFilter;
2718 		VK_FILTER_LINEAR,							//	VkFilter				minFilter;
2719 		VK_SAMPLER_MIPMAP_MODE_LINEAR,				//	VkSamplerMipmapMode		mipmapMode;
2720 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				//	VkSamplerAddressMode	addressModeU;
2721 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				//	VkSamplerAddressMode	addressModeV;
2722 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				//	VkSamplerAddressMode	addressModeW;
2723 		0.0f,										//	float					mipLodBias;
2724 		VK_FALSE,									//	VkBool32				anisotropyEnable;
2725 		0.0f,										//	float					maxAnisotropy;
2726 		VK_FALSE,									//	VkBool32				compareEnable;
2727 		VK_COMPARE_OP_NEVER,						//	VkCompareOp				compareOp;
2728 		0.0f,										//	float					minLod;
2729 		static_cast<float>(texMipLevels),			//	float					maxLod;
2730 		VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,		//	VkBorderColor			borderColor;
2731 		VK_FALSE,									//	VkBool32				unnormalizedCoordinates;
2732 	};
2733 	const auto sampler = createSampler(vkd, device, &samplerCreateInfo);
2734 
2735 	// Descriptor pool and set.
2736 	DescriptorPoolBuilder poolBuilder;
2737 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
2738 	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2739 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
2740 
2741 	// Update descriptor set.
2742 	DescriptorSetUpdateBuilder setUpdateBuilder;
2743 	const auto combinedSamplerInfo = makeDescriptorImageInfo(sampler.get(), texView.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2744 	setUpdateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &combinedSamplerInfo);
2745 	setUpdateBuilder.update(vkd, device);
2746 
2747 	// Render pass and framebuffer.
2748 	const auto renderPass	= makeRenderPass(vkd, device, imageFormat);
2749 	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorExtent.width, colorExtent.height);
2750 
2751 	// Shader modules.
2752 	const auto&	binaries	= m_context.getBinaryCollection();
2753 	const auto	vertModule	= createShaderModule(vkd, device, binaries.get("vert"));
2754 	const auto	fragModule	= createShaderModule(vkd, device, binaries.get("frag"));
2755 
2756 	// Viewports and scissors.
2757 	std::vector<VkViewport>	viewports	(1u, makeViewport(colorExtent));
2758 	std::vector<VkRect2D>	scissors	(1u, makeRect2D(colorExtent));
2759 
2760 	// Pipeline.
2761 	const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2762 
2763 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
2764 		vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
2765 		renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
2766 		0u/*subpass*/, 0u/*patchControlPoints*/, &vertexInputState);
2767 
2768 	// Command pool and buffer.
2769 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
2770 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2771 	const auto cmdBuffer	= cmdBufferPtr.get();
2772 
2773 	beginCommandBuffer(vkd, cmdBuffer);
2774 
2775 	// Move the whole texture to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
2776 	const auto preClearBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), texSRR);
2777 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preClearBarrier);
2778 
2779 	// Fill each texture mip level with a different pseudorandom nonzero color.
2780 	std::vector<tcu::Vec4> levelColors;
2781 	de::Random rnd (m_params.randomSeed);
2782 
2783 	levelColors.reserve(texMipLevels);
2784 
2785 	const auto minColor = 0.004f; // Slightly above 1/255.
2786 	const auto maxColor = 1.0f;
2787 
2788 	for (uint32_t level = 0u; level < texMipLevels; ++level)
2789 	{
2790 		const auto r			= rnd.getFloat(minColor, maxColor);
2791 		const auto g			= rnd.getFloat(minColor, maxColor);
2792 		const auto b			= rnd.getFloat(minColor, maxColor);
2793 		const auto a			= rnd.getFloat(minColor, maxColor);
2794 		const auto levelColor	= makeClearValueColorF32(r, g, b, a).color;
2795 		const auto levelRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2796 
2797 		levelColors.emplace_back(r, g, b, a);
2798 		vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &levelColor, 1u, &levelRange);
2799 	}
2800 
2801 	// Move the whole texture to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
2802 	const auto postClearBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.get(), texSRR);
2803 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, &postClearBarrier);
2804 
2805 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2806 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2807 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2808 	vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); // This has to match the vertex shader.
2809 	endRenderPass(vkd, cmdBuffer);
2810 
2811 	// Copy color buffer to verification buffer.
2812 	const auto postColorBarier = makeImageMemoryBarrier(
2813 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2814 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2815 		colorBuffer.get(), colorSRR);
2816 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postColorBarier);
2817 
2818 	const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
2819 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, &copyRegion);
2820 
2821 	const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2822 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
2823 
2824 	endCommandBuffer(vkd, cmdBuffer);
2825 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2826 
2827 	// Verify color buffer.
2828 	invalidateAlloc(vkd, device, verifBufferAlloc);
2829 	tcu::ConstPixelBufferAccess resultAccess (tcuFormat, iColorExtent, verifBufferData);
2830 
2831 	const auto		resultColor		= resultAccess.getPixel(0, 0);
2832 	const auto		srcLevelColor	= levelColors.at(minLodU);
2833 	const auto		compColor		= srcLevelColor[m_params.component];
2834 	const auto		expectedColor	= (m_params.needsRobustness2() // This has to match the fragment shader.
2835 									? tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)
2836 									: tcu::Vec4(compColor, compColor, compColor, 1.0f));
2837 	const auto		threshold		= (m_params.needsRobustness2()
2838 									? 0.0f
2839 									: 0.005f); // 1/255 < 0.005 < 2/255
2840 
2841 	const auto		diff			= abs(resultColor - expectedColor);
2842 	const tcu::Vec4	thresholdVec	(threshold, threshold, threshold, 0.0f);
2843 	const auto		thresholdMet	= tcu::lessThanEqual(diff, thresholdVec);
2844 
2845 	if (!tcu::boolAll(thresholdMet))
2846 	{
2847 		std::ostringstream msg;
2848 		msg << "Unexpected output buffer color: expected " << expectedColor << " but found " << resultColor << " [diff=" << diff << "]";
2849 		TCU_FAIL(msg.str());
2850 	}
2851 
2852 	return tcu::TestStatus::pass("Pass");
2853 }
2854 
2855 #endif // CTS_USES_VULKANSC
2856 
2857 } // anonymous
2858 
2859 #ifndef CTS_USES_VULKANSC
2860 
2861 namespace util {
2862 
2863 template <>
checkTextureSupport(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2864 void checkTextureSupport (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
2865 {
2866 	if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2867 	{
2868 		context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2869 		vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2870 		imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2871 		imageViewMinLodFeatures.pNext = DE_NULL;
2872 
2873 		vk::VkPhysicalDeviceFeatures2 features2;
2874 
2875 		features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2876 		features2.pNext = &imageViewMinLodFeatures;
2877 
2878 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2879 
2880 		if (imageViewMinLodFeatures.minLod == DE_FALSE)
2881 			TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2882 	}
2883 }
2884 
2885 template <>
checkTextureSupport(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)2886 void checkTextureSupport (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
2887 {
2888 	if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2889 	{
2890 		context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2891 		vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2892 		imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2893 		imageViewMinLodFeatures.pNext = DE_NULL;
2894 
2895 		vk::VkPhysicalDeviceFeatures2 features2;
2896 
2897 		features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2898 		features2.pNext = &imageViewMinLodFeatures;
2899 
2900 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2901 
2902 		if (imageViewMinLodFeatures.minLod == DE_FALSE)
2903 			TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2904 	}
2905 }
2906 
2907 template <>
checkTextureSupport(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2908 void checkTextureSupport (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
2909 {
2910 	if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2911 	{
2912 		context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2913 		vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2914 		imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2915 		imageViewMinLodFeatures.pNext = DE_NULL;
2916 
2917 		vk::VkPhysicalDeviceFeatures2 features2;
2918 
2919 		features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2920 		features2.pNext = &imageViewMinLodFeatures;
2921 
2922 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2923 
2924 		if (imageViewMinLodFeatures.minLod == DE_FALSE)
2925 			TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2926 	}
2927 }
2928 
2929 } // util
2930 
populateMinLodGatherGroup(tcu::TestCaseGroup * minLodGatherGroup)2931 void populateMinLodGatherGroup (tcu::TestCaseGroup* minLodGatherGroup)
2932 {
2933 	using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2934 
2935 	const struct
2936 	{
2937 		GatherMinLod	minLod;
2938 		const char*		name;
2939 	} GatherMinLodCases[] =
2940 	{
2941 		{ GatherMinLod::MINLOD_0_1,		"minlod_0_1"	},
2942 		{ GatherMinLod::MINLOD_1_1,		"minlod_1_1"	},
2943 	};
2944 
2945 	const struct
2946 	{
2947 		int				component;
2948 		const char*		name;
2949 	} ComponentCases[] =
2950 	{
2951 		{ 0,	"component_0"	},
2952 		{ 1,	"component_1"	},
2953 		{ 2,	"component_2"	},
2954 		{ 3,	"component_3"	},
2955 	};
2956 
2957 	auto& testCtx = minLodGatherGroup->getTestContext();
2958 
2959 	for (const auto& gatherMinLodCase : GatherMinLodCases)
2960 	{
2961 		GroupPtr minLodGroup (new tcu::TestCaseGroup(testCtx, gatherMinLodCase.name));
2962 
2963 		for (const auto& componentCase : ComponentCases)
2964 		{
2965 			const uint32_t seed	= (static_cast<uint32_t>(gatherMinLodCase.minLod) + 1000u) * 1000u
2966 								+ (static_cast<uint32_t>(componentCase.component) + 1000u);
2967 
2968 			GatherParams params;
2969 			params.randomSeed	= seed;
2970 			params.minLod		= gatherMinLodCase.minLod;
2971 			params.component	= componentCase.component;
2972 
2973 			minLodGroup->addChild(new TextureGatherMinLodTest(testCtx, componentCase.name, params));
2974 		}
2975 
2976 		minLodGatherGroup->addChild(minLodGroup.release());
2977 	}
2978 }
2979 
2980 #endif // CTS_USES_VULKANSC
2981 
populateTextureMipmappingTests(tcu::TestCaseGroup * textureMipmappingTests)2982 void populateTextureMipmappingTests (tcu::TestCaseGroup* textureMipmappingTests)
2983 {
2984 	tcu::TestContext&	testCtx		= textureMipmappingTests->getTestContext();
2985 
2986 	static const struct
2987 	{
2988 		const char*				name;
2989 		const Sampler::WrapMode	mode;
2990 	} wrapModes[] =
2991 	{
2992 		{ "clamp",		Sampler::CLAMP_TO_EDGE		},
2993 		{ "repeat",		Sampler::REPEAT_GL			},
2994 		{ "mirror",		Sampler::MIRRORED_REPEAT_GL	}
2995 	};
2996 
2997 	static const struct
2998 	{
2999 		const char*					name;
3000 		const Sampler::FilterMode	mode;
3001 	} minFilterModes[] =
3002 	{
3003 		{ "nearest_nearest",	Sampler::NEAREST_MIPMAP_NEAREST	},
3004 		{ "linear_nearest",		Sampler::LINEAR_MIPMAP_NEAREST	},
3005 		{ "nearest_linear",		Sampler::NEAREST_MIPMAP_LINEAR	},
3006 		{ "linear_linear",		Sampler::LINEAR_MIPMAP_LINEAR	}
3007 	};
3008 
3009 	static const struct
3010 	{
3011 		const char*					name;
3012 		const Sampler::FilterMode	mode;
3013 	} magFilterModes[] =
3014 	{
3015 		{ "nearest",	Sampler::NEAREST},
3016 		{ "linear",		Sampler::LINEAR}
3017 	};
3018 
3019 
3020 	static const struct
3021 	{
3022 		const CoordType		type;
3023 		const char*			name;
3024 	} coordTypes[] =
3025 	{
3026 		// Mipmapping with translated and scaled coordinates
3027 		{ COORDTYPE_BASIC,		"basic"},
3028 		// Mipmapping with affine coordinate transform
3029 		{ COORDTYPE_AFFINE,		"affine"},
3030 		// Mipmapping with perspective projection
3031 		{ COORDTYPE_PROJECTED,	"projected"}
3032 	};
3033 
3034 	static const struct
3035 	{
3036 		const char*		name;
3037 		const int		width;
3038 		const int		height;
3039 	} tex2DSizes[] =
3040 	{
3041 		{ DE_NULL,		64, 64 }, // Default.
3042 		{ "npot",		63, 57 },
3043 		{ "non_square",	32, 64 }
3044 	};
3045 
3046 	static const struct
3047 	{
3048 		const char*		name;
3049 		const int		width;
3050 		const int		height;
3051 		const int		depth;
3052 	} tex3DSizes[] =
3053 	{
3054 		{ DE_NULL,		32, 32, 32 }, // Default.
3055 		{ "npot",		33, 29, 27 }
3056 	};
3057 
3058 	const int cubeMapSize = 64;
3059 
3060 	static const struct
3061 	{
3062 		const CoordType		type;
3063 		const char*			name;
3064 	} cubeCoordTypes[] =
3065 	{
3066 		// Mipmapping with translated and scaled coordinates
3067 		{ COORDTYPE_BASIC,		"basic"},
3068 		// Mipmapping with perspective projection
3069 		{ COORDTYPE_PROJECTED,	"projected"},
3070 		// User-supplied bias value
3071 		{ COORDTYPE_BASIC_BIAS,	"bias"}
3072 	};
3073 
3074 	// 2D cases.
3075 	{
3076 		// 2D Mipmap Filtering
3077 		de::MovePtr<tcu::TestCaseGroup>	group2D				(new tcu::TestCaseGroup(testCtx, "2d"));
3078 
3079 		de::MovePtr<tcu::TestCaseGroup>	biasGroup2D			(new tcu::TestCaseGroup(testCtx, "bias", "User-supplied bias value"));
3080 		de::MovePtr<tcu::TestCaseGroup>	minLodGroup2D		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
3081 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroup2D		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
3082 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroup2D	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
3083 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroup2D		(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
3084 
3085 #ifndef CTS_USES_VULKANSC
3086 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup2D	(new tcu::TestCaseGroup(testCtx, "image_view_min_lod", "VK_EXT_image_view_min_lod tests"));
3087 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup2D	(new tcu::TestCaseGroup(testCtx, "min_lod", "ImageView's minLod"));
3088 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup2D	(new tcu::TestCaseGroup(testCtx, "base_level", "ImageView's minLod with base level different than one"));
3089 #endif // CTS_USES_VULKANSC
3090 
3091 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3092 		{
3093 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup		(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name));
3094 
3095 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3096 			{
3097 				for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3098 				{
3099 					// Add non_square variants to basic cases only.
3100 					int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
3101 
3102 					for (int size = 0; size < sizeEnd; size++)
3103 					{
3104 						Texture2DMipmapTestCaseParameters	testParameters;
3105 
3106 						testParameters.coordType	= coordTypes[coordType].type;
3107 						testParameters.minFilter	= minFilterModes[minFilter].mode;
3108 						testParameters.wrapS		= wrapModes[wrapMode].mode;
3109 						testParameters.wrapT		= wrapModes[wrapMode].mode;
3110 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
3111 						testParameters.width		= tex2DSizes[size].width;
3112 						testParameters.height		= tex2DSizes[size].height;
3113 						testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3114 						testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3115 
3116 						std::ostringstream name;
3117 						name << minFilterModes[minFilter].name
3118 							 << "_" << wrapModes[wrapMode].name;
3119 
3120 						if (tex2DSizes[size].name)
3121 							name << "_" << tex2DSizes[size].name;
3122 
3123 						coordTypeGroup->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), testParameters));
3124 					}
3125 				}
3126 			}
3127 
3128 			group2D->addChild(coordTypeGroup.release());
3129 		}
3130 
3131 		// 2D bias variants.
3132 		{
3133 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3134 			{
3135 				Texture2DMipmapTestCaseParameters	testParameters;
3136 
3137 				testParameters.coordType	= COORDTYPE_BASIC_BIAS;
3138 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3139 				testParameters.magFilter	= minFilterModes[minFilter].mode;
3140 				testParameters.wrapS		= Sampler::REPEAT_GL;
3141 				testParameters.wrapT		= Sampler::REPEAT_GL;
3142 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
3143 				testParameters.width		= tex2DSizes[0].width;
3144 				testParameters.height		= tex2DSizes[0].height;
3145 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3146 				testParameters.programs.push_back(PROGRAM_2D_FLOAT_BIAS);
3147 
3148 				std::ostringstream name;
3149 				name << minFilterModes[minFilter].name;
3150 
3151 				biasGroup2D->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), testParameters));
3152 			}
3153 		}
3154 
3155 		// 2D LOD controls.
3156 		{
3157 			// MIN_LOD
3158 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3159 			{
3160 				Texture2DMipmapTestCaseParameters	testParameters;
3161 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3162 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3163 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3164 
3165 				minLodGroup2D->addChild(new TextureTestCase<Texture2DMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3166 			}
3167 
3168 			// MAX_LOD
3169 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3170 			{
3171 				Texture2DMipmapTestCaseParameters	testParameters;
3172 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3173 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3174 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3175 
3176 				maxLodGroup2D->addChild(new TextureTestCase<Texture2DMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3177 			}
3178 		}
3179 
3180 		{
3181 			// BASE_LEVEL
3182 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3183 			{
3184 				Texture2DMipmapTestCaseParameters	testParameters;
3185 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3186 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3187 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3188 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3189 
3190 				baseLevelGroup2D->addChild(new TextureTestCase<Texture2DBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3191 			}
3192 
3193 			// MAX_LEVEL
3194 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3195 			{
3196 				Texture2DMipmapTestCaseParameters	testParameters;
3197 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3198 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3199 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3200 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3201 
3202 				maxLevelGroup2D->addChild(new TextureTestCase<Texture2DMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3203 			}
3204 		}
3205 
3206 		// 2D VK_EXT_image_view_min_lod.
3207 #ifndef CTS_USES_VULKANSC
3208 		{
3209 			// MIN_LOD
3210 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3211 			{
3212 				Texture2DMipmapTestCaseParameters	testParameters;
3213 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3214 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3215 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3216 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3217 
3218 				imageViewMinLodGroup2D->addChild(new TextureTestCase<Texture2DImageViewMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3219 
3220 				std::ostringstream name;
3221 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3222 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3223 				imageViewMinLodGroup2D->addChild(new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3224 			}
3225 
3226 			// BASE_LEVEL
3227 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3228 			{
3229 				Texture2DMipmapTestCaseParameters	testParameters;
3230 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3231 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3232 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3233 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3234 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3235 
3236 				imageViewMinLodBaseLevelGroup2D->addChild(new TextureTestCase<Texture2DImageViewMinLodBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3237 
3238 				std::ostringstream name;
3239 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3240 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3241 				imageViewMinLodBaseLevelGroup2D->addChild(new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3242 			}
3243 
3244 			imageViewMinLodExtGroup2D->addChild(imageViewMinLodGroup2D.release());
3245 			imageViewMinLodExtGroup2D->addChild(imageViewMinLodBaseLevelGroup2D.release());
3246 		}
3247 #endif // CTS_USES_VULKANSC
3248 
3249 		group2D->addChild(biasGroup2D.release());
3250 		group2D->addChild(minLodGroup2D.release());
3251 		group2D->addChild(maxLodGroup2D.release());
3252 		group2D->addChild(baseLevelGroup2D.release());
3253 		group2D->addChild(maxLevelGroup2D.release());
3254 #ifndef CTS_USES_VULKANSC
3255 		group2D->addChild(imageViewMinLodExtGroup2D.release());
3256 #endif // CTS_USES_VULKANSC
3257 
3258 		textureMipmappingTests->addChild(group2D.release());
3259 	}
3260 
3261 	// Cubemap cases.
3262 	{
3263 		de::MovePtr<tcu::TestCaseGroup>	groupCube			(new tcu::TestCaseGroup(testCtx, "cubemap", "Cube Mipmap Filtering"));
3264 
3265 		de::MovePtr<tcu::TestCaseGroup>	minLodGroupCube		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
3266 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroupCube		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
3267 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
3268 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
3269 
3270 #ifndef CTS_USES_VULKANSC
3271 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroupCube	(new tcu::TestCaseGroup(testCtx, "image_view_min_lod", "VK_EXT_image_view_min_lod tests"));
3272 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroupCube	(new tcu::TestCaseGroup(testCtx, "min_lod", "ImageView's minLod"));
3273 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "base_level", "ImageView's minLod with base level different than one"));
3274 #endif // CTS_USES_VULKANSC
3275 
3276 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
3277 		{
3278 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup	(new tcu::TestCaseGroup(testCtx, cubeCoordTypes[coordType].name));
3279 
3280 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3281 			{
3282 				for (int magFilter = 0; magFilter < DE_LENGTH_OF_ARRAY(magFilterModes); magFilter++)
3283 				{
3284 					for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3285 					{
3286 						TextureCubeMipmapTestCaseParameters	testParameters;
3287 
3288 						testParameters.coordType		= cubeCoordTypes[coordType].type;
3289 						testParameters.minFilter		= minFilterModes[minFilter].mode;
3290 						testParameters.magFilter		= magFilterModes[magFilter].mode;
3291 						testParameters.minFilterName	= minFilterModes[minFilter].name;
3292 						testParameters.wrapS			= wrapModes[wrapMode].mode;
3293 						testParameters.wrapT			= wrapModes[wrapMode].mode;
3294 						testParameters.format			= VK_FORMAT_R8G8B8A8_UNORM;
3295 						testParameters.size				= cubeMapSize;
3296 						testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3297 
3298 						if (testParameters.coordType == COORDTYPE_BASIC_BIAS)
3299 							testParameters.programs.push_back(PROGRAM_CUBE_FLOAT_BIAS);
3300 						else
3301 							testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3302 
3303 						std::ostringstream name;
3304 						name << minFilterModes[minFilter].name
3305 							 << "_" << magFilterModes[magFilter].name
3306 							 << "_" << wrapModes[wrapMode].name;
3307 
3308 						coordTypeGroup->addChild(new TextureTestCase<TextureCubeMipmapTestInstance>(testCtx, name.str().c_str(), testParameters));
3309 					}
3310 				}
3311 			}
3312 
3313 			groupCube->addChild(coordTypeGroup.release());
3314 		}
3315 
3316 		// Cubemap LOD controls.
3317 		{
3318 			// MIN_LOD
3319 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3320 			{
3321 				TextureCubeMipmapTestCaseParameters	testParameters;
3322 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3323 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3324 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3325 
3326 				minLodGroupCube->addChild(new TextureTestCase<TextureCubeMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3327 			}
3328 
3329 			// MAX_LOD
3330 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3331 			{
3332 				TextureCubeMipmapTestCaseParameters	testParameters;
3333 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3334 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3335 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3336 
3337 				maxLodGroupCube->addChild(new TextureTestCase<TextureCubeMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3338 			}
3339 		}
3340 
3341 		{
3342 			// BASE_LEVEL
3343 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3344 			{
3345 				TextureCubeMipmapTestCaseParameters	testParameters;
3346 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3347 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3348 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3349 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3350 
3351 				baseLevelGroupCube->addChild(new TextureTestCase<TextureCubeBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3352 			}
3353 
3354 			// MAX_LEVEL
3355 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3356 			{
3357 				TextureCubeMipmapTestCaseParameters	testParameters;
3358 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3359 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3360 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3361 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3362 
3363 				maxLevelGroupCube->addChild(new TextureTestCase<TextureCubeMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3364 			}
3365 		}
3366 
3367 		// Cube VK_EXT_image_view_min_lod.
3368 #ifndef CTS_USES_VULKANSC
3369 		{
3370 			// MIN_LOD
3371 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3372 			{
3373 				TextureCubeMipmapTestCaseParameters	testParameters;
3374 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3375 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3376 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3377 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3378 
3379 				imageViewMinLodGroupCube->addChild(new TextureTestCase<TextureCubeImageViewMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3380 			}
3381 
3382 			// BASE_LEVEL
3383 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3384 			{
3385 				TextureCubeMipmapTestCaseParameters	testParameters;
3386 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3387 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3388 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3389 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3390 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3391 
3392 				imageViewMinLodBaseLevelGroupCube->addChild(new TextureTestCase<TextureCubeImageViewMinLodBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3393 			}
3394 
3395 			imageViewMinLodExtGroupCube->addChild(imageViewMinLodGroupCube.release());
3396 			imageViewMinLodExtGroupCube->addChild(imageViewMinLodBaseLevelGroupCube.release());
3397 		}
3398 #endif // CTS_USES_VULKANSC
3399 
3400 		groupCube->addChild(minLodGroupCube.release());
3401 		groupCube->addChild(maxLodGroupCube.release());
3402 		groupCube->addChild(baseLevelGroupCube.release());
3403 		groupCube->addChild(maxLevelGroupCube.release());
3404 #ifndef CTS_USES_VULKANSC
3405 		groupCube->addChild(imageViewMinLodExtGroupCube.release());
3406 #endif // CTS_USES_VULKANSC
3407 
3408 		textureMipmappingTests->addChild(groupCube.release());
3409 	}
3410 
3411 	// 3D cases.
3412 	{
3413 		de::MovePtr<tcu::TestCaseGroup>	group3D				(new tcu::TestCaseGroup(testCtx, "3d", "3D Mipmap Filtering"));
3414 
3415 		de::MovePtr<tcu::TestCaseGroup>	biasGroup3D			(new tcu::TestCaseGroup(testCtx, "bias", "User-supplied bias value"));
3416 		de::MovePtr<tcu::TestCaseGroup>	minLodGroup3D		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
3417 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroup3D		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
3418 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroup3D	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
3419 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroup3D		(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
3420 
3421 #ifndef CTS_USES_VULKANSC
3422 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup3D	(new tcu::TestCaseGroup(testCtx, "image_view_min_lod", "VK_EXT_image_view_min_lod tests"));
3423 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup3D	(new tcu::TestCaseGroup(testCtx, "min_lod", "ImageView's minLod"));
3424 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup3D	(new tcu::TestCaseGroup(testCtx, "base_level", "ImageView's minLod with base level different than one"));
3425 #endif // CTS_USES_VULKANSC
3426 
3427 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3428 		{
3429 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup	(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name));
3430 
3431 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3432 			{
3433 				for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3434 				{
3435 					// Add other size variants to basic cases only.
3436 					int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
3437 
3438 					Texture3DMipmapTestCaseParameters	testParameters;
3439 
3440 					testParameters.coordType		= coordTypes[coordType].type;
3441 					testParameters.minFilter		= minFilterModes[minFilter].mode;
3442 					testParameters.minFilterName	= minFilterModes[minFilter].name;
3443 					testParameters.wrapR			= wrapModes[wrapMode].mode;
3444 					testParameters.wrapS			= wrapModes[wrapMode].mode;
3445 					testParameters.wrapT			= wrapModes[wrapMode].mode;
3446 					testParameters.format			= VK_FORMAT_R8G8B8A8_UNORM;
3447 					testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3448 					testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3449 
3450 					for (int size = 0; size < sizeEnd; size++)
3451 					{
3452 						testParameters.width			= tex3DSizes[size].width;
3453 						testParameters.height			= tex3DSizes[size].height;
3454 						testParameters.depth			= tex3DSizes[size].depth;
3455 
3456 						std::ostringstream name;
3457 						name << minFilterModes[minFilter].name
3458 							 << "_" << wrapModes[wrapMode].name;
3459 
3460 						if (tex3DSizes[size].name)
3461 							name << "_" << tex3DSizes[size].name;
3462 
3463 						coordTypeGroup->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(testCtx, name.str().c_str(), testParameters));
3464 					}
3465 				}
3466 			}
3467 
3468 			group3D->addChild(coordTypeGroup.release());
3469 		}
3470 
3471 		// 3D bias variants.
3472 		{
3473 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3474 			{
3475 				Texture3DMipmapTestCaseParameters	testParameters;
3476 				testParameters.coordType			= COORDTYPE_BASIC_BIAS;
3477 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3478 				testParameters.wrapR				= Sampler::REPEAT_GL;
3479 				testParameters.wrapS				= Sampler::REPEAT_GL;
3480 				testParameters.wrapT				= Sampler::REPEAT_GL;
3481 				testParameters.format				= VK_FORMAT_R8G8B8A8_UNORM;
3482 				testParameters.width				= tex3DSizes[0].width;
3483 				testParameters.height				= tex3DSizes[0].height;
3484 				testParameters.depth				= tex3DSizes[0].depth;
3485 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3486 				testParameters.programs.push_back(PROGRAM_3D_FLOAT_BIAS);
3487 
3488 				biasGroup3D->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3489 			}
3490 		}
3491 
3492 		// 3D LOD controls.
3493 		{
3494 			// MIN_LOD
3495 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3496 			{
3497 				Texture3DMipmapTestCaseParameters	testParameters;
3498 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3499 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3500 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3501 
3502 				minLodGroup3D->addChild(new TextureTestCase<Texture3DMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3503 			}
3504 
3505 			// MAX_LOD
3506 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3507 			{
3508 				Texture3DMipmapTestCaseParameters	testParameters;
3509 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3510 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3511 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3512 
3513 				maxLodGroup3D->addChild(new TextureTestCase<Texture3DMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3514 			}
3515 		}
3516 
3517 		{
3518 			// BASE_LEVEL
3519 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3520 			{
3521 				Texture3DMipmapTestCaseParameters	testParameters;
3522 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3523 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3524 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3525 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3526 
3527 				baseLevelGroup3D->addChild(new TextureTestCase<Texture3DBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3528 			}
3529 
3530 			// MAX_LEVEL
3531 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3532 			{
3533 				Texture3DMipmapTestCaseParameters	testParameters;
3534 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3535 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3536 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3537 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3538 
3539 				maxLevelGroup3D->addChild(new TextureTestCase<Texture3DMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3540 			}
3541 		}
3542 
3543 		// 3D VK_EXT_image_view_min_lod.
3544 #ifndef CTS_USES_VULKANSC
3545 		{
3546 			// MIN_LOD
3547 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3548 			{
3549 				Texture3DMipmapTestCaseParameters	testParameters;
3550 				testParameters.minFilter				= minFilterModes[minFilter].mode;
3551 				testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
3552 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3553 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3554 
3555 				imageViewMinLodGroup3D->addChild(new TextureTestCase<Texture3DImageViewMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3556 
3557 				std::ostringstream name;
3558 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3559 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3560 				imageViewMinLodGroup3D->addChild(new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3561 			}
3562 
3563 			// BASE_LEVEL
3564 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3565 			{
3566 				Texture3DMipmapTestCaseParameters testParameters;
3567 				testParameters.minFilter				= minFilterModes[minFilter].mode;
3568 				testParameters.minFilterName			= minFilterModes[minFilter].name;
3569 				testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
3570 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3571 				testParameters.testType					= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3572 
3573 
3574 				imageViewMinLodBaseLevelGroup3D->addChild(new TextureTestCase<Texture3DImageViewMinLodBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, testParameters));
3575 
3576 				std::ostringstream name;
3577 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3578 				testParameters.testType					= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3579 				imageViewMinLodBaseLevelGroup3D->addChild(new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3580 			}
3581 
3582 			imageViewMinLodExtGroup3D->addChild(imageViewMinLodGroup3D.release());
3583 			imageViewMinLodExtGroup3D->addChild(imageViewMinLodBaseLevelGroup3D.release());
3584 		}
3585 #endif // CTS_USES_VULKANSC
3586 
3587 		group3D->addChild(biasGroup3D.release());
3588 		group3D->addChild(minLodGroup3D.release());
3589 		group3D->addChild(maxLodGroup3D.release());
3590 		group3D->addChild(baseLevelGroup3D.release());
3591 		group3D->addChild(maxLevelGroup3D.release());
3592 #ifndef CTS_USES_VULKANSC
3593 		group3D->addChild(imageViewMinLodExtGroup3D.release());
3594 #endif // CTS_USES_VULKANSC
3595 
3596 		textureMipmappingTests->addChild(group3D.release());
3597 	}
3598 
3599 #ifndef CTS_USES_VULKANSC
3600 	{
3601 		// Test minLod with textureGather operations
3602 		const auto minLodGatherGroup = createTestGroup(testCtx, "min_lod_gather", populateMinLodGatherGroup, destroyDeviceHelpers);
3603 		textureMipmappingTests->addChild(minLodGatherGroup);
3604 	}
3605 #endif // CTS_USES_VULKANSC
3606 }
3607 
createTextureMipmappingTests(tcu::TestContext & testCtx)3608 tcu::TestCaseGroup* createTextureMipmappingTests (tcu::TestContext& testCtx)
3609 {
3610 	return createTestGroup(testCtx, "mipmap", populateTextureMipmappingTests);
3611 }
3612 
3613 } // texture
3614 } // vkt
3615