• 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 string&								description,
2056 																 const Texture2DMipmapTestCaseParameters&	params);
2057 	~Texture2DImageViewMinLodIntTexCoordTest					(void);
2058 	void						initPrograms					(SourceCollections& sourceCollections) const;
2059 	TestInstance*				createInstance					(Context& context) const;
2060 	void						checkSupport					(Context& context) const;
2061 
2062 protected:
2063 	const Texture2DMipmapTestCaseParameters	m_params;
2064 };
2065 
Texture2DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const string & description,const Texture2DMipmapTestCaseParameters & params)2066 Texture2DImageViewMinLodIntTexCoordTest::Texture2DImageViewMinLodIntTexCoordTest (tcu::TestContext&							testContext,
2067 																				  const string&								name,
2068 																				  const string&								description,
2069 																				  const Texture2DMipmapTestCaseParameters&	params)
2070 	: vkt::TestCase	(testContext, name, description)
2071 	, m_params		(params)
2072 {
2073 }
2074 
~Texture2DImageViewMinLodIntTexCoordTest(void)2075 Texture2DImageViewMinLodIntTexCoordTest::~Texture2DImageViewMinLodIntTexCoordTest (void)
2076 {
2077 }
2078 
initPrograms(SourceCollections & sourceCollections) const2079 void Texture2DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections& sourceCollections) const
2080 {
2081 	static const char* vertShader =
2082 		"#version 450\n"
2083 		"layout(location = 0) in vec4 a_position;\n"
2084 		"layout(location = 1) in vec2 a_texCoord;\n"
2085 		"out gl_PerVertex { vec4 gl_Position; };\n"
2086 		"\n"
2087 		"void main (void)\n"
2088 		"{\n"
2089 		"	gl_Position = a_position;\n"
2090 		"}\n";
2091 
2092 	static const char* fragShader =
2093 		"#version 450\n"
2094 		"layout(location = 0) out vec4 outColor;\n"
2095 		"layout (set=0, binding=0, std140) uniform Block \n"
2096 		"{\n"
2097 		"  float u_bias;\n"
2098 		"  float u_ref;\n"
2099 		"  vec4 u_colorScale;\n"
2100 		"  vec4 u_colorBias;\n"
2101 		"  int u_lod;\n"
2102 		"};\n\n"
2103 		"layout (set=1, binding=0) uniform sampler2D u_sampler;\n"
2104 		"void main (void)\n"
2105 		"{\n"
2106 		"  ivec2 texCoord = ivec2(0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2107 		"  outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2108 		"}\n";
2109 	sourceCollections.glslSources.add("vertex_2D_FETCH_LOD") << glu::VertexSource(vertShader);
2110 	sourceCollections.glslSources.add("fragment_2D_FETCH_LOD") << glu::FragmentSource(fragShader);
2111 }
2112 
checkSupport(Context & context) const2113 void Texture2DImageViewMinLodIntTexCoordTest::checkSupport(Context& context) const
2114 {
2115 	DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2116 
2117 	context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2118 	context.requireDeviceFunctionality("VK_EXT_robustness2");
2119 	vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2120 	imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2121 	imageViewMinLodFeatures.pNext = DE_NULL;
2122 
2123 	VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2124 	robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2125 	robustness2Features.pNext = &imageViewMinLodFeatures;
2126 	vk::VkPhysicalDeviceFeatures2 features2;
2127 
2128 	features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2129 	features2.pNext = &robustness2Features;
2130 
2131 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2132 
2133 	if (imageViewMinLodFeatures.minLod == DE_FALSE)
2134 		TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2135 
2136 	if (robustness2Features.robustImageAccess2 == DE_FALSE)
2137 		TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2138 }
2139 
createInstance(Context & context) const2140 TestInstance* Texture2DImageViewMinLodIntTexCoordTest::createInstance(Context& context) const
2141 {
2142 	if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2143 		return new Texture2DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2144 	else
2145 		return new Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2146 }
2147 
2148 class Texture3DImageViewMinLodIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2149 {
2150 public:
Texture3DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2151 	Texture3DImageViewMinLodIntTexCoordTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
2152 		: Texture3DLodControlTestInstance(context, testParameters)
2153 		, m_testParam (testParameters)
2154 	{
2155 	}
2156 
2157 protected:
2158 	const Texture3DMipmapTestCaseParameters m_testParam;
2159 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2160 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
2161 	{
2162 		de::Random rnd(cellNdx + 1);
2163 
2164 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2165 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2166 		return rnd.getFloat(minValue, (float)maxLevel);
2167 	}
2168 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2169 	int getLodTexelFetch (int cellNdx, int baseLevel, int maxLevel) const
2170 	{
2171 		de::Random rnd(cellNdx + 1);
2172 		return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2173 	}
2174 
getReferenceParams(ReferenceParams & params,int cellNdx)2175 	void getReferenceParams (ReferenceParams& params, int cellNdx)
2176 	{
2177 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2178 		params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2179 		params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2180 	}
2181 };
2182 
2183 class Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2184 {
2185 public:
Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2186 	Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
2187 		: Texture3DLodControlTestInstance(context, testParameters)
2188 		, m_testParam (testParameters)
2189 	{
2190 	}
2191 
2192 protected:
2193 	const Texture3DMipmapTestCaseParameters m_testParam;
2194 
getBaseLevel(int cellNdx) const2195 	int getBaseLevel (int cellNdx) const
2196 	{
2197 		const int	numLevels	= deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth)))+1;
2198 		const int	baseLevel	= (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
2199 
2200 		return baseLevel;
2201 	}
2202 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2203 	float getImageViewMinLod (int cellNdx, int baseLevel, int maxLevel) const
2204 	{
2205 		de::Random rnd(cellNdx + 1);
2206 
2207 		// baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2208 		float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2209 		return rnd.getFloat(minValue, (float)maxLevel);
2210 	}
2211 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2212 	int getLodTexelFetch (int cellNdx, int baseLevel, int maxLevel) const
2213 	{
2214 		de::Random rnd(cellNdx + 1);
2215 		return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2216 	}
2217 
getReferenceParams(ReferenceParams & params,int cellNdx)2218 	void getReferenceParams (ReferenceParams& params, int cellNdx)
2219 	{
2220 		params.baseLevel = getBaseLevel(cellNdx);
2221 		params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2222 		params.samplerType = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2223 		params.lodTexelFetch = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2224 	}
2225 };
2226 
2227 class Texture3DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2228 {
2229 public:
2230 	Texture3DImageViewMinLodIntTexCoordTest						(tcu::TestContext&							testContext,
2231 																 const string&								name,
2232 																 const string&								description,
2233 																 const Texture3DMipmapTestCaseParameters&	params);
2234 	~Texture3DImageViewMinLodIntTexCoordTest					(void);
2235 	void						initPrograms					(SourceCollections& sourceCollections) const;
2236 	TestInstance*				createInstance					(Context& context) const;
2237 	void						checkSupport					(Context& context) const;
2238 
2239 protected:
2240 	const Texture3DMipmapTestCaseParameters	m_params;
2241 };
2242 
Texture3DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const string & description,const Texture3DMipmapTestCaseParameters & params)2243 Texture3DImageViewMinLodIntTexCoordTest::Texture3DImageViewMinLodIntTexCoordTest (tcu::TestContext&							testContext,
2244 																				  const string&								name,
2245 																				  const string&								description,
2246 																				  const Texture3DMipmapTestCaseParameters&	params)
2247 	: vkt::TestCase	(testContext, name, description)
2248 	, m_params		(params)
2249 {
2250 }
2251 
~Texture3DImageViewMinLodIntTexCoordTest(void)2252 Texture3DImageViewMinLodIntTexCoordTest::~Texture3DImageViewMinLodIntTexCoordTest (void)
2253 {
2254 }
2255 
initPrograms(SourceCollections & sourceCollections) const2256 void Texture3DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections& sourceCollections) const
2257 {
2258 	static const char* vertShader =
2259 		"#version 450\n"
2260 		"layout(location = 0) in vec4 a_position;\n"
2261 		"layout(location = 1) in vec3 a_texCoord;\n"
2262 		"out gl_PerVertex { vec4 gl_Position; };\n"
2263 		"\n"
2264 		"void main (void)\n"
2265 		"{\n"
2266 		"	gl_Position = a_position;\n"
2267 		"}\n";
2268 
2269 	static const char* fragShader =
2270 		"#version 450\n"
2271 		"layout(location = 0) out vec4 outColor;\n"
2272 		"layout (set=0, binding=0, std140) uniform Block \n"
2273 		"{\n"
2274 		"  float u_bias;\n"
2275 		"  float u_ref;\n"
2276 		"  vec4 u_colorScale;\n"
2277 		"  vec4 u_colorBias;\n"
2278 		"  int u_lod;\n"
2279 		"};\n\n"
2280 		"layout (set=1, binding=0) uniform sampler3D u_sampler;\n"
2281 		"void main (void)\n"
2282 		"{\n"
2283 		"  ivec3 texCoord = ivec3(0,0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2284 		"  outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2285 		"}\n";
2286 	sourceCollections.glslSources.add("vertex_3D_FETCH_LOD") << glu::VertexSource(vertShader);
2287 	sourceCollections.glslSources.add("fragment_3D_FETCH_LOD") << glu::FragmentSource(fragShader);
2288 }
2289 
checkSupport(Context & context) const2290 void Texture3DImageViewMinLodIntTexCoordTest::checkSupport(Context& context) const
2291 {
2292 	DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2293 
2294 	context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2295 	context.requireDeviceFunctionality("VK_EXT_robustness2");
2296 	vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2297 	imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2298 	imageViewMinLodFeatures.pNext = DE_NULL;
2299 
2300 	VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2301 	robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2302 	robustness2Features.pNext = &imageViewMinLodFeatures;
2303 	vk::VkPhysicalDeviceFeatures2 features2;
2304 
2305 	features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2306 	features2.pNext = &robustness2Features;
2307 
2308 	context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2309 
2310 	if (imageViewMinLodFeatures.minLod == DE_FALSE)
2311 		TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2312 
2313 	if (robustness2Features.robustImageAccess2 == DE_FALSE)
2314 		TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2315 }
2316 
createInstance(Context & context) const2317 TestInstance* Texture3DImageViewMinLodIntTexCoordTest::createInstance(Context& context) const
2318 {
2319 	if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2320 		return new Texture3DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2321 	else
2322 	   return new Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2323 }
2324 
2325 // Texture gather tests.
2326 enum class GatherMinLod
2327 {
2328 	MINLOD_0_1,		// 0.1
2329 	MINLOD_1_1,		// 1.1
2330 };
2331 
2332 struct GatherParams
2333 {
2334 	uint32_t		randomSeed;	// Seed for the pseudorandom number generator.
2335 	GatherMinLod	minLod;		// Idea: make it 0.1 or 1.1
2336 	int				component;	// 0, 1, 2, 3 for the gather operation.
2337 
getNumericMinLodvkt::texture::__anon60d989fa0111::GatherParams2338 	float getNumericMinLod (void) const
2339 	{
2340 		float lod = 0.0f;
2341 
2342 		switch (minLod)
2343 		{
2344 		case GatherMinLod::MINLOD_0_1:	lod = 0.1f; break;
2345 		case GatherMinLod::MINLOD_1_1:	lod = 1.1f; break;
2346 		default: DE_ASSERT(false); break;
2347 		}
2348 
2349 		return lod;
2350 	}
2351 
getMinLodIntegervkt::texture::__anon60d989fa0111::GatherParams2352 	uint32_t getMinLodInteger (void) const
2353 	{
2354 		uint32_t lod = 0u;
2355 
2356 		switch (minLod)
2357 		{
2358 		case GatherMinLod::MINLOD_0_1:	lod = 0u; break;
2359 		case GatherMinLod::MINLOD_1_1:	lod = 1u; break;
2360 		default: DE_ASSERT(false); break;
2361 		}
2362 
2363 		return lod;
2364 	}
2365 
needsRobustness2vkt::texture::__anon60d989fa0111::GatherParams2366 	bool needsRobustness2 (void) const
2367 	{
2368 		return (getNumericMinLod() >= 1.0f);
2369 	}
2370 };
2371 
2372 class TextureGatherMinLodTest : public vkt::TestCase
2373 {
2374 public:
TextureGatherMinLodTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const GatherParams & params)2375 					TextureGatherMinLodTest		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const GatherParams& params)
2376 						: vkt::TestCase	(testCtx, name, description)
2377 						, m_params		(params)
2378 						{}
~TextureGatherMinLodTest(void)2379 	virtual			~TextureGatherMinLodTest	(void) {}
2380 
2381 	void			initPrograms				(vk::SourceCollections& programCollection) const override;
2382 	TestInstance*	createInstance				(Context& context) const override;
2383 	void			checkSupport				(Context& context) const override;
2384 
2385 protected:
2386 	GatherParams	m_params;
2387 };
2388 
2389 class TextureGatherMinLodInstance : public vkt::TestInstance
2390 {
2391 public:
TextureGatherMinLodInstance(Context & context,const GatherParams & params)2392 					TextureGatherMinLodInstance		(Context& context, const GatherParams& params)
2393 						: vkt::TestInstance	(context)
2394 						, m_params			(params)
2395 						{}
~TextureGatherMinLodInstance(void)2396 	virtual			~TextureGatherMinLodInstance	(void) {}
2397 
2398 	tcu::TestStatus	iterate							(void) override;
2399 
2400 protected:
2401 	GatherParams	m_params;
2402 };
2403 
2404 // Test idea: create texture with 3 levels, each of them having a unique nonzero color. Render gathering the color from a fixed
2405 // position in that texture (center point). Use the minLod parameter when creating the view to control which one should be the
2406 // output color. If minLod is 0.1, minLodInteger should be 0 and gathering from the base level is defined, so we should get the
2407 // output color from the base level. If minLod is 1.1, gathering texels from the base level requires robustness2 and will result in
2408 // zeros instead of the color from levels 0 or 1.
initPrograms(vk::SourceCollections & programCollection) const2409 void TextureGatherMinLodTest::initPrograms (vk::SourceCollections &programCollection) const
2410 {
2411 	// Full screen triangle covering the whole viewport.
2412 	std::ostringstream vert;
2413 	vert
2414 		<< "#version 450\n"
2415 		<< "\n"
2416 		<< "vec2 positions[3] = vec2[](\n"
2417 		<< "    vec2(-1.0, -1.0),\n"
2418 		<< "    vec2(3.0, -1.0),\n"
2419 		<< "    vec2(-1.0, 3.0)\n"
2420 		<< ");\n"
2421 		<< "\n"
2422 		<< "void main (void)\n"
2423 		<< "{\n"
2424 		<< "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
2425 		<< "}\n"
2426 		;
2427 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2428 
2429 	std::ostringstream frag;
2430 	frag
2431 		<< "#version 450\n"
2432 		<< "\n"
2433 		<< "layout (location=0) out vec4 outColor;\n"
2434 		<< "layout (set=0, binding=0) uniform sampler2D u_sampler;\n"
2435 		<< "\n"
2436 		<< "void main (void)\n"
2437 		<< "{\n"
2438 		<< "    const vec2 gatherCoords = vec2(0.5, 0.5);\n"
2439 		<< "    const vec4 gatherRes = textureGather(u_sampler, gatherCoords, " << m_params.component << ");\n"
2440 		<< "    outColor = vec4(gatherRes.xyz, 1.0);\n"
2441 		<< "}\n";
2442 		;
2443 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2444 }
2445 
checkSupport(Context & context) const2446 void TextureGatherMinLodTest::checkSupport (Context& context) const
2447 {
2448 	context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2449 	context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2450 
2451 	if (m_params.needsRobustness2())
2452 	{
2453 		context.requireDeviceFunctionality("VK_EXT_robustness2");
2454 
2455 		VkPhysicalDeviceRobustness2FeaturesEXT	robustness2Features	= initVulkanStructure();
2456 		VkPhysicalDeviceFeatures2				features2			= initVulkanStructure(&robustness2Features);
2457 
2458 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2459 
2460 		if (robustness2Features.robustImageAccess2 == DE_FALSE)
2461 			TCU_THROW(NotSupportedError, "robustImageAccess2 not supported");
2462 	}
2463 }
2464 
createInstance(Context & context) const2465 TestInstance* TextureGatherMinLodTest::createInstance (Context& context) const
2466 {
2467 	return new TextureGatherMinLodInstance(context, m_params);
2468 }
2469 
2470 // Device helper: this is needed because we sometimes need a custom device with robustImageAccess2.
2471 class DeviceHelper
2472 {
2473 public:
~DeviceHelper()2474 	virtual ~DeviceHelper () {}
2475 	virtual const DeviceInterface&	getDeviceInterface	(void) const = 0;
2476 	virtual VkDevice				getDevice			(void) const = 0;
2477 	virtual uint32_t				getQueueFamilyIndex	(void) const = 0;
2478 	virtual VkQueue					getQueue			(void) const = 0;
2479 	virtual Allocator&				getAllocator		(void) const = 0;
2480 };
2481 
2482 // This one just reuses the default device from the context.
2483 class ContextDeviceHelper : public DeviceHelper
2484 {
2485 public:
ContextDeviceHelper(Context & context)2486 	ContextDeviceHelper (Context& context)
2487 		: m_deviceInterface		(context.getDeviceInterface())
2488 		, m_device				(context.getDevice())
2489 		, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
2490 		, m_queue				(context.getUniversalQueue())
2491 		, m_allocator			(context.getDefaultAllocator())
2492 		{}
2493 
~ContextDeviceHelper()2494 	virtual ~ContextDeviceHelper () {}
2495 
getDeviceInterface(void) const2496 	const DeviceInterface&	getDeviceInterface	(void) const override	{ return m_deviceInterface;		}
getDevice(void) const2497 	VkDevice				getDevice			(void) const override	{ return m_device;				}
getQueueFamilyIndex(void) const2498 	uint32_t				getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const2499 	VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const2500 	Allocator&				getAllocator		(void) const override	{ return m_allocator;			}
2501 
2502 protected:
2503 	const DeviceInterface&	m_deviceInterface;
2504 	const VkDevice			m_device;
2505 	const uint32_t			m_queueFamilyIndex;
2506 	const VkQueue			m_queue;
2507 	Allocator&				m_allocator;
2508 };
2509 
2510 // This one creates a new device with robustImageAccess2.
2511 class RobustImageAccess2DeviceHelper : public DeviceHelper
2512 {
2513 public:
RobustImageAccess2DeviceHelper(Context & context)2514 	RobustImageAccess2DeviceHelper (Context& context)
2515 	{
2516 		const auto&	vkp				= context.getPlatformInterface();
2517 		const auto&	vki				= context.getInstanceInterface();
2518 		const auto	instance		= context.getInstance();
2519 		const auto	physicalDevice	= context.getPhysicalDevice();
2520 		const auto	queuePriority	= 1.0f;
2521 
2522 		// Queue index first.
2523 		m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2524 
2525 		// Create a universal queue that supports graphics and compute.
2526 		const VkDeviceQueueCreateInfo queueParams =
2527 		{
2528 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
2529 			DE_NULL,									// const void*					pNext;
2530 			0u,											// VkDeviceQueueCreateFlags		flags;
2531 			m_queueFamilyIndex,							// deUint32						queueFamilyIndex;
2532 			1u,											// deUint32						queueCount;
2533 			&queuePriority								// const float*					pQueuePriorities;
2534 		};
2535 
2536 		const char* extensions[] =
2537 		{
2538 			"VK_EXT_robustness2",
2539 		};
2540 
2541 		VkPhysicalDeviceImageViewMinLodFeaturesEXT	minLodfeatures		= initVulkanStructure();
2542 		VkPhysicalDeviceRobustness2FeaturesEXT		robustness2Features	= initVulkanStructure(&minLodfeatures);
2543 		VkPhysicalDeviceFeatures2					features2			= initVulkanStructure(&robustness2Features);
2544 
2545 		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
2546 
2547 		const VkDeviceCreateInfo deviceCreateInfo =
2548 		{
2549 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,					//sType;
2550 			&features2,												//pNext;
2551 			0u,														//flags
2552 			1u,														//queueRecordCount;
2553 			&queueParams,											//pRequestedQueues;
2554 			0u,														//layerCount;
2555 			nullptr,												//ppEnabledLayerNames;
2556 			static_cast<uint32_t>(de::arrayLength(extensions)),		// deUint32							enabledExtensionCount;
2557 			extensions,												// const char* const*				ppEnabledExtensionNames;
2558 			nullptr,												//pEnabledFeatures;
2559 		};
2560 
2561 		m_device	= createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
2562 		m_vkd		.reset(new DeviceDriver(vkp, instance, m_device.get()));
2563 		m_queue		= getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
2564 		m_allocator	.reset(new SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
2565 	}
2566 
~RobustImageAccess2DeviceHelper()2567 	virtual ~RobustImageAccess2DeviceHelper () {}
2568 
getDeviceInterface(void) const2569 	const DeviceInterface&	getDeviceInterface	(void) const override	{ return *m_vkd;				}
getDevice(void) const2570 	VkDevice				getDevice			(void) const override	{ return m_device.get();		}
getQueueFamilyIndex(void) const2571 	uint32_t				getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const2572 	VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const2573 	Allocator&				getAllocator		(void) const override	{ return *m_allocator;			}
2574 
2575 protected:
2576 	Move<VkDevice>						m_device;
2577 	std::unique_ptr<DeviceDriver>		m_vkd;
2578 	deUint32							m_queueFamilyIndex;
2579 	VkQueue								m_queue;
2580 	std::unique_ptr<SimpleAllocator>	m_allocator;
2581 };
2582 
2583 std::unique_ptr<DeviceHelper> g_robustness2DeviceHelper;
2584 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
2585 
getDeviceHelper(Context & context,bool needsRobustness2)2586 DeviceHelper& getDeviceHelper (Context& context, bool needsRobustness2)
2587 {
2588 	if (needsRobustness2)
2589 	{
2590 		if (!g_robustness2DeviceHelper)
2591 			g_robustness2DeviceHelper.reset(new RobustImageAccess2DeviceHelper(context));
2592 		return *g_robustness2DeviceHelper;
2593 	}
2594 
2595 	if (!g_contextDeviceHelper)
2596 		g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
2597 	return *g_contextDeviceHelper;
2598 }
2599 
2600 // Cleanup function for the test group.
destroyDeviceHelpers(tcu::TestCaseGroup *)2601 void destroyDeviceHelpers (tcu::TestCaseGroup*)
2602 {
2603 	g_robustness2DeviceHelper.reset(nullptr);
2604 	g_contextDeviceHelper.reset(nullptr);
2605 }
2606 
iterate(void)2607 tcu::TestStatus TextureGatherMinLodInstance::iterate (void)
2608 {
2609 	const auto&	deviceHelper	= getDeviceHelper(m_context, m_params.needsRobustness2());
2610 	const auto&	vkd				= deviceHelper.getDeviceInterface();
2611 	const auto	device			= deviceHelper.getDevice();
2612 	const auto	queueIndex		= deviceHelper.getQueueFamilyIndex();
2613 	const auto	queue			= deviceHelper.getQueue();
2614 	auto&		alloc			= deviceHelper.getAllocator();
2615 
2616 	const auto			imageFormat		= VK_FORMAT_R8G8B8A8_UNORM;
2617 	const auto			tcuFormat		= mapVkFormat(imageFormat);
2618 	const auto			colorExtent		= makeExtent3D(1u, 1u, 1u);
2619 	const tcu::IVec3	iColorExtent	(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth));
2620 	const auto			texExtent		= makeExtent3D(8u, 8u, 1u);
2621 	const auto			texMipLevels	= 3u;
2622 	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2623 	const auto			texUsage		= (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2624 	const auto			minLodF			= m_params.getNumericMinLod();
2625 	const auto			minLodU			= m_params.getMinLodInteger();
2626 	const tcu::Vec4		clearColor		(0.0f, 0.0f, 0.0f, 1.0f);
2627 
2628 	// Color attachment: a simple 1x1 image.
2629 	const VkImageCreateInfo colorCreateInfo =
2630 	{
2631 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2632 		nullptr,								//	const void*				pNext;
2633 		0u,										//	VkImageCreateFlags		flags;
2634 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2635 		imageFormat,							//	VkFormat				format;
2636 		colorExtent,							//	VkExtent3D				extent;
2637 		1u,										//	uint32_t				mipLevels;
2638 		1u,										//	uint32_t				arrayLayers;
2639 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2640 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2641 		colorUsage,								//	VkImageUsageFlags		usage;
2642 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2643 		0u,										//	uint32_t				queueFamilyIndexCount;
2644 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2645 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2646 	};
2647 
2648 	ImageWithMemory	colorBuffer		(vkd, device, alloc, colorCreateInfo, MemoryRequirement::Any);
2649 	const auto		colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2650 	const auto		colorSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2651 	const auto		colorBufferView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2652 
2653 	// Texture: an 8x8 image with several mip levels.
2654 	const VkImageCreateInfo texCreateInfo =
2655 	{
2656 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
2657 		nullptr,								//	const void*				pNext;
2658 		0u,										//	VkImageCreateFlags		flags;
2659 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
2660 		imageFormat,							//	VkFormat				format;
2661 		texExtent,								//	VkExtent3D				extent;
2662 		texMipLevels,							//	uint32_t				mipLevels;
2663 		1u,										//	uint32_t				arrayLayers;
2664 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
2665 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
2666 		texUsage,								//	VkImageUsageFlags		usage;
2667 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
2668 		0u,										//	uint32_t				queueFamilyIndexCount;
2669 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
2670 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
2671 	};
2672 
2673 	ImageWithMemory texture (vkd, device, alloc, texCreateInfo, MemoryRequirement::Any);
2674 	const auto texSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texMipLevels, 0u, 1u);
2675 
2676 	DE_ASSERT(texMipLevels > 0u);
2677 	DE_ASSERT(minLodU < texMipLevels);
2678 
2679 	const VkImageViewMinLodCreateInfoEXT texMinLodInfo =
2680 	{
2681 		VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT,	//	VkStructureType	sType;
2682 		nullptr,												//	const void*		pNext;
2683 		minLodF,												//	float			minLod;
2684 	};
2685 
2686 	const VkImageViewCreateInfo texViewCreateInfo =
2687 	{
2688 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	//	VkStructureType			sType;
2689 		&texMinLodInfo,								//	const void*				pNext;
2690 		0u,											//	VkImageViewCreateFlags	flags;
2691 		texture.get(),								//	VkImage					image;
2692 		VK_IMAGE_VIEW_TYPE_2D,						//	VkImageViewType			viewType;
2693 		imageFormat,								//	VkFormat				format;
2694 		makeComponentMappingRGBA(),					//	VkComponentMapping		components;
2695 		texSRR,										//	VkImageSubresourceRange	subresourceRange;
2696 	};
2697 
2698 	const auto texView = createImageView(vkd, device, &texViewCreateInfo);
2699 
2700 	// Verification buffer for the color attachment.
2701 	const auto			verifBufferSize			= static_cast<VkDeviceSize>(iColorExtent.x() * iColorExtent.y() * iColorExtent.z() * tcu::getPixelSize(tcuFormat));
2702 	const auto			verifBufferCreateInfo	= makeBufferCreateInfo(verifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2703 	BufferWithMemory	verifBuffer				(vkd, device, alloc, verifBufferCreateInfo, MemoryRequirement::HostVisible);
2704 	auto&				verifBufferAlloc		= verifBuffer.getAllocation();
2705 	void*				verifBufferData			= verifBufferAlloc.getHostPtr();
2706 
2707 	// Descriptor set layout.
2708 	DescriptorSetLayoutBuilder setLayoutBuilder;
2709 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
2710 	const auto setLayout = setLayoutBuilder.build(vkd, device);
2711 
2712 	// Pipeline layout.
2713 	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
2714 
2715 	// Sampler.
2716 	const VkSamplerCreateInfo samplerCreateInfo =
2717 	{
2718 		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		//	VkStructureType			sType;
2719 		nullptr,									//	const void*				pNext;
2720 		0u,											//	VkSamplerCreateFlags	flags;
2721 		VK_FILTER_LINEAR,							//	VkFilter				magFilter;
2722 		VK_FILTER_LINEAR,							//	VkFilter				minFilter;
2723 		VK_SAMPLER_MIPMAP_MODE_LINEAR,				//	VkSamplerMipmapMode		mipmapMode;
2724 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				//	VkSamplerAddressMode	addressModeU;
2725 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				//	VkSamplerAddressMode	addressModeV;
2726 		VK_SAMPLER_ADDRESS_MODE_REPEAT,				//	VkSamplerAddressMode	addressModeW;
2727 		0.0f,										//	float					mipLodBias;
2728 		VK_FALSE,									//	VkBool32				anisotropyEnable;
2729 		0.0f,										//	float					maxAnisotropy;
2730 		VK_FALSE,									//	VkBool32				compareEnable;
2731 		VK_COMPARE_OP_NEVER,						//	VkCompareOp				compareOp;
2732 		0.0f,										//	float					minLod;
2733 		static_cast<float>(texMipLevels),			//	float					maxLod;
2734 		VK_BORDER_COLOR_INT_TRANSPARENT_BLACK,		//	VkBorderColor			borderColor;
2735 		VK_FALSE,									//	VkBool32				unnormalizedCoordinates;
2736 	};
2737 	const auto sampler = createSampler(vkd, device, &samplerCreateInfo);
2738 
2739 	// Descriptor pool and set.
2740 	DescriptorPoolBuilder poolBuilder;
2741 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
2742 	const auto descriptorPool	= poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2743 	const auto descriptorSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
2744 
2745 	// Update descriptor set.
2746 	DescriptorSetUpdateBuilder setUpdateBuilder;
2747 	const auto combinedSamplerInfo = makeDescriptorImageInfo(sampler.get(), texView.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2748 	setUpdateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &combinedSamplerInfo);
2749 	setUpdateBuilder.update(vkd, device);
2750 
2751 	// Render pass and framebuffer.
2752 	const auto renderPass	= makeRenderPass(vkd, device, imageFormat);
2753 	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorExtent.width, colorExtent.height);
2754 
2755 	// Shader modules.
2756 	const auto&	binaries	= m_context.getBinaryCollection();
2757 	const auto	vertModule	= createShaderModule(vkd, device, binaries.get("vert"));
2758 	const auto	fragModule	= createShaderModule(vkd, device, binaries.get("frag"));
2759 
2760 	// Viewports and scissors.
2761 	std::vector<VkViewport>	viewports	(1u, makeViewport(colorExtent));
2762 	std::vector<VkRect2D>	scissors	(1u, makeRect2D(colorExtent));
2763 
2764 	// Pipeline.
2765 	const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2766 
2767 	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
2768 		vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
2769 		renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
2770 		0u/*subpass*/, 0u/*patchControlPoints*/, &vertexInputState);
2771 
2772 	// Command pool and buffer.
2773 	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
2774 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2775 	const auto cmdBuffer	= cmdBufferPtr.get();
2776 
2777 	beginCommandBuffer(vkd, cmdBuffer);
2778 
2779 	// Move the whole texture to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
2780 	const auto preClearBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), texSRR);
2781 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preClearBarrier);
2782 
2783 	// Fill each texture mip level with a different pseudorandom nonzero color.
2784 	std::vector<tcu::Vec4> levelColors;
2785 	de::Random rnd (m_params.randomSeed);
2786 
2787 	levelColors.reserve(texMipLevels);
2788 
2789 	const auto minColor = 0.004f; // Slightly above 1/255.
2790 	const auto maxColor = 1.0f;
2791 
2792 	for (uint32_t level = 0u; level < texMipLevels; ++level)
2793 	{
2794 		const auto r			= rnd.getFloat(minColor, maxColor);
2795 		const auto g			= rnd.getFloat(minColor, maxColor);
2796 		const auto b			= rnd.getFloat(minColor, maxColor);
2797 		const auto a			= rnd.getFloat(minColor, maxColor);
2798 		const auto levelColor	= makeClearValueColorF32(r, g, b, a).color;
2799 		const auto levelRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2800 
2801 		levelColors.emplace_back(r, g, b, a);
2802 		vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &levelColor, 1u, &levelRange);
2803 	}
2804 
2805 	// Move the whole texture to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
2806 	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);
2807 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, &postClearBarrier);
2808 
2809 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2810 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2811 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2812 	vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); // This has to match the vertex shader.
2813 	endRenderPass(vkd, cmdBuffer);
2814 
2815 	// Copy color buffer to verification buffer.
2816 	const auto postColorBarier = makeImageMemoryBarrier(
2817 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2818 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2819 		colorBuffer.get(), colorSRR);
2820 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postColorBarier);
2821 
2822 	const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
2823 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, &copyRegion);
2824 
2825 	const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2826 	cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
2827 
2828 	endCommandBuffer(vkd, cmdBuffer);
2829 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2830 
2831 	// Verify color buffer.
2832 	invalidateAlloc(vkd, device, verifBufferAlloc);
2833 	tcu::ConstPixelBufferAccess resultAccess (tcuFormat, iColorExtent, verifBufferData);
2834 
2835 	const auto		resultColor		= resultAccess.getPixel(0, 0);
2836 	const auto		srcLevelColor	= levelColors.at(minLodU);
2837 	const auto		compColor		= srcLevelColor[m_params.component];
2838 	const auto		expectedColor	= (m_params.needsRobustness2() // This has to match the fragment shader.
2839 									? tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)
2840 									: tcu::Vec4(compColor, compColor, compColor, 1.0f));
2841 	const auto		threshold		= (m_params.needsRobustness2()
2842 									? 0.0f
2843 									: 0.005f); // 1/255 < 0.005 < 2/255
2844 
2845 	const auto		diff			= abs(resultColor - expectedColor);
2846 	const tcu::Vec4	thresholdVec	(threshold, threshold, threshold, 0.0f);
2847 	const auto		thresholdMet	= tcu::lessThanEqual(diff, thresholdVec);
2848 
2849 	if (!tcu::boolAll(thresholdMet))
2850 	{
2851 		std::ostringstream msg;
2852 		msg << "Unexpected output buffer color: expected " << expectedColor << " but found " << resultColor << " [diff=" << diff << "]";
2853 		TCU_FAIL(msg.str());
2854 	}
2855 
2856 	return tcu::TestStatus::pass("Pass");
2857 }
2858 
2859 #endif // CTS_USES_VULKANSC
2860 
2861 } // anonymous
2862 
2863 #ifndef CTS_USES_VULKANSC
2864 
2865 namespace util {
2866 
2867 template <>
checkTextureSupport(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2868 void checkTextureSupport (Context& context, const Texture2DMipmapTestCaseParameters& testParameters)
2869 {
2870 	if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2871 	{
2872 		context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2873 		vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2874 		imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2875 		imageViewMinLodFeatures.pNext = DE_NULL;
2876 
2877 		vk::VkPhysicalDeviceFeatures2 features2;
2878 
2879 		features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2880 		features2.pNext = &imageViewMinLodFeatures;
2881 
2882 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2883 
2884 		if (imageViewMinLodFeatures.minLod == DE_FALSE)
2885 			TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2886 	}
2887 }
2888 
2889 template <>
checkTextureSupport(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)2890 void checkTextureSupport (Context& context, const TextureCubeMipmapTestCaseParameters& testParameters)
2891 {
2892 	if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2893 	{
2894 		context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2895 		vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2896 		imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2897 		imageViewMinLodFeatures.pNext = DE_NULL;
2898 
2899 		vk::VkPhysicalDeviceFeatures2 features2;
2900 
2901 		features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2902 		features2.pNext = &imageViewMinLodFeatures;
2903 
2904 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2905 
2906 		if (imageViewMinLodFeatures.minLod == DE_FALSE)
2907 			TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2908 	}
2909 }
2910 
2911 template <>
checkTextureSupport(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2912 void checkTextureSupport (Context& context, const Texture3DMipmapTestCaseParameters& testParameters)
2913 {
2914 	if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2915 	{
2916 		context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2917 		vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2918 		imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2919 		imageViewMinLodFeatures.pNext = DE_NULL;
2920 
2921 		vk::VkPhysicalDeviceFeatures2 features2;
2922 
2923 		features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2924 		features2.pNext = &imageViewMinLodFeatures;
2925 
2926 		context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2927 
2928 		if (imageViewMinLodFeatures.minLod == DE_FALSE)
2929 			TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2930 	}
2931 }
2932 
2933 } // util
2934 
populateMinLodGatherGroup(tcu::TestCaseGroup * minLodGatherGroup)2935 void populateMinLodGatherGroup (tcu::TestCaseGroup* minLodGatherGroup)
2936 {
2937 	using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2938 
2939 	const struct
2940 	{
2941 		GatherMinLod	minLod;
2942 		const char*		name;
2943 	} GatherMinLodCases[] =
2944 	{
2945 		{ GatherMinLod::MINLOD_0_1,		"minlod_0_1"	},
2946 		{ GatherMinLod::MINLOD_1_1,		"minlod_1_1"	},
2947 	};
2948 
2949 	const struct
2950 	{
2951 		int				component;
2952 		const char*		name;
2953 	} ComponentCases[] =
2954 	{
2955 		{ 0,	"component_0"	},
2956 		{ 1,	"component_1"	},
2957 		{ 2,	"component_2"	},
2958 		{ 3,	"component_3"	},
2959 	};
2960 
2961 	auto& testCtx = minLodGatherGroup->getTestContext();
2962 
2963 	for (const auto& gatherMinLodCase : GatherMinLodCases)
2964 	{
2965 		GroupPtr minLodGroup (new tcu::TestCaseGroup(testCtx, gatherMinLodCase.name, ""));
2966 
2967 		for (const auto& componentCase : ComponentCases)
2968 		{
2969 			const uint32_t seed	= (static_cast<uint32_t>(gatherMinLodCase.minLod) + 1000u) * 1000u
2970 								+ (static_cast<uint32_t>(componentCase.component) + 1000u);
2971 
2972 			GatherParams params;
2973 			params.randomSeed	= seed;
2974 			params.minLod		= gatherMinLodCase.minLod;
2975 			params.component	= componentCase.component;
2976 
2977 			minLodGroup->addChild(new TextureGatherMinLodTest(testCtx, componentCase.name, "", params));
2978 		}
2979 
2980 		minLodGatherGroup->addChild(minLodGroup.release());
2981 	}
2982 }
2983 
2984 #endif // CTS_USES_VULKANSC
2985 
populateTextureMipmappingTests(tcu::TestCaseGroup * textureMipmappingTests)2986 void populateTextureMipmappingTests (tcu::TestCaseGroup* textureMipmappingTests)
2987 {
2988 	tcu::TestContext&	testCtx		= textureMipmappingTests->getTestContext();
2989 
2990 	static const struct
2991 	{
2992 		const char*				name;
2993 		const Sampler::WrapMode	mode;
2994 	} wrapModes[] =
2995 	{
2996 		{ "clamp",		Sampler::CLAMP_TO_EDGE		},
2997 		{ "repeat",		Sampler::REPEAT_GL			},
2998 		{ "mirror",		Sampler::MIRRORED_REPEAT_GL	}
2999 	};
3000 
3001 	static const struct
3002 	{
3003 		const char*					name;
3004 		const Sampler::FilterMode	mode;
3005 	} minFilterModes[] =
3006 	{
3007 		{ "nearest_nearest",	Sampler::NEAREST_MIPMAP_NEAREST	},
3008 		{ "linear_nearest",		Sampler::LINEAR_MIPMAP_NEAREST	},
3009 		{ "nearest_linear",		Sampler::NEAREST_MIPMAP_LINEAR	},
3010 		{ "linear_linear",		Sampler::LINEAR_MIPMAP_LINEAR	}
3011 	};
3012 
3013 	static const struct
3014 	{
3015 		const char*					name;
3016 		const Sampler::FilterMode	mode;
3017 	} magFilterModes[] =
3018 	{
3019 		{ "nearest",	Sampler::NEAREST},
3020 		{ "linear",		Sampler::LINEAR}
3021 	};
3022 
3023 
3024 	static const struct
3025 	{
3026 		const CoordType		type;
3027 		const char*			name;
3028 		const char*			desc;
3029 	} coordTypes[] =
3030 	{
3031 		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
3032 		{ COORDTYPE_AFFINE,		"affine",		"Mipmapping with affine coordinate transform"		},
3033 		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			}
3034 	};
3035 
3036 	static const struct
3037 	{
3038 		const char*		name;
3039 		const int		width;
3040 		const int		height;
3041 	} tex2DSizes[] =
3042 	{
3043 		{ DE_NULL,		64, 64 }, // Default.
3044 		{ "npot",		63, 57 },
3045 		{ "non_square",	32, 64 }
3046 	};
3047 
3048 	static const struct
3049 	{
3050 		const char*		name;
3051 		const int		width;
3052 		const int		height;
3053 		const int		depth;
3054 	} tex3DSizes[] =
3055 	{
3056 		{ DE_NULL,		32, 32, 32 }, // Default.
3057 		{ "npot",		33, 29, 27 }
3058 	};
3059 
3060 	const int cubeMapSize = 64;
3061 
3062 	static const struct
3063 	{
3064 		const CoordType		type;
3065 		const char*			name;
3066 		const char*			desc;
3067 	} cubeCoordTypes[] =
3068 	{
3069 		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
3070 		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			},
3071 		{ COORDTYPE_BASIC_BIAS,	"bias",			"User-supplied bias value"							}
3072 	};
3073 
3074 	// 2D cases.
3075 	{
3076 		de::MovePtr<tcu::TestCaseGroup>	group2D				(new tcu::TestCaseGroup(testCtx, "2d", "2D Mipmap Filtering"));
3077 
3078 		de::MovePtr<tcu::TestCaseGroup>	biasGroup2D			(new tcu::TestCaseGroup(testCtx, "bias", "User-supplied bias value"));
3079 		de::MovePtr<tcu::TestCaseGroup>	minLodGroup2D		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
3080 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroup2D		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
3081 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroup2D	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
3082 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroup2D		(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
3083 
3084 #ifndef CTS_USES_VULKANSC
3085 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup2D	(new tcu::TestCaseGroup(testCtx, "image_view_min_lod", "VK_EXT_image_view_min_lod tests"));
3086 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup2D	(new tcu::TestCaseGroup(testCtx, "min_lod", "ImageView's minLod"));
3087 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup2D	(new tcu::TestCaseGroup(testCtx, "base_level", "ImageView's minLod with base level different than one"));
3088 #endif // CTS_USES_VULKANSC
3089 
3090 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3091 		{
3092 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup		(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name, coordTypes[coordType].desc));
3093 
3094 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3095 			{
3096 				for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3097 				{
3098 					// Add non_square variants to basic cases only.
3099 					int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
3100 
3101 					for (int size = 0; size < sizeEnd; size++)
3102 					{
3103 						Texture2DMipmapTestCaseParameters	testParameters;
3104 
3105 						testParameters.coordType	= coordTypes[coordType].type;
3106 						testParameters.minFilter	= minFilterModes[minFilter].mode;
3107 						testParameters.wrapS		= wrapModes[wrapMode].mode;
3108 						testParameters.wrapT		= wrapModes[wrapMode].mode;
3109 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
3110 						testParameters.width		= tex2DSizes[size].width;
3111 						testParameters.height		= tex2DSizes[size].height;
3112 						testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3113 						testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3114 
3115 						std::ostringstream name;
3116 						name << minFilterModes[minFilter].name
3117 							 << "_" << wrapModes[wrapMode].name;
3118 
3119 						if (tex2DSizes[size].name)
3120 							name << "_" << tex2DSizes[size].name;
3121 
3122 						coordTypeGroup->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
3123 					}
3124 				}
3125 			}
3126 
3127 			group2D->addChild(coordTypeGroup.release());
3128 		}
3129 
3130 		// 2D bias variants.
3131 		{
3132 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3133 			{
3134 				Texture2DMipmapTestCaseParameters	testParameters;
3135 
3136 				testParameters.coordType	= COORDTYPE_BASIC_BIAS;
3137 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3138 				testParameters.magFilter	= minFilterModes[minFilter].mode;
3139 				testParameters.wrapS		= Sampler::REPEAT_GL;
3140 				testParameters.wrapT		= Sampler::REPEAT_GL;
3141 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
3142 				testParameters.width		= tex2DSizes[0].width;
3143 				testParameters.height		= tex2DSizes[0].height;
3144 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3145 				testParameters.programs.push_back(PROGRAM_2D_FLOAT_BIAS);
3146 
3147 				std::ostringstream name;
3148 				name << minFilterModes[minFilter].name;
3149 
3150 				biasGroup2D->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
3151 			}
3152 		}
3153 
3154 		// 2D LOD controls.
3155 		{
3156 			// MIN_LOD
3157 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3158 			{
3159 				Texture2DMipmapTestCaseParameters	testParameters;
3160 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3161 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3162 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3163 
3164 				minLodGroup2D->addChild(new TextureTestCase<Texture2DMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3165 			}
3166 
3167 			// MAX_LOD
3168 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3169 			{
3170 				Texture2DMipmapTestCaseParameters	testParameters;
3171 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3172 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3173 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3174 
3175 				maxLodGroup2D->addChild(new TextureTestCase<Texture2DMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3176 			}
3177 		}
3178 
3179 		{
3180 			// BASE_LEVEL
3181 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3182 			{
3183 				Texture2DMipmapTestCaseParameters	testParameters;
3184 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3185 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3186 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3187 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3188 
3189 				baseLevelGroup2D->addChild(new TextureTestCase<Texture2DBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3190 			}
3191 
3192 			// MAX_LEVEL
3193 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3194 			{
3195 				Texture2DMipmapTestCaseParameters	testParameters;
3196 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3197 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3198 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3199 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3200 
3201 				maxLevelGroup2D->addChild(new TextureTestCase<Texture2DMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3202 			}
3203 		}
3204 
3205 		// 2D VK_EXT_image_view_min_lod.
3206 #ifndef CTS_USES_VULKANSC
3207 		{
3208 			// MIN_LOD
3209 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3210 			{
3211 				Texture2DMipmapTestCaseParameters	testParameters;
3212 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3213 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3214 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3215 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3216 
3217 				imageViewMinLodGroup2D->addChild(new TextureTestCase<Texture2DImageViewMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3218 
3219 				std::ostringstream name;
3220 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3221 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3222 				imageViewMinLodGroup2D->addChild(new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), "", testParameters));
3223 			}
3224 
3225 			// BASE_LEVEL
3226 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3227 			{
3228 				Texture2DMipmapTestCaseParameters	testParameters;
3229 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3230 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3231 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3232 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3233 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3234 
3235 				imageViewMinLodBaseLevelGroup2D->addChild(new TextureTestCase<Texture2DImageViewMinLodBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3236 
3237 				std::ostringstream name;
3238 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3239 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3240 				imageViewMinLodBaseLevelGroup2D->addChild(new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), "", testParameters));
3241 			}
3242 
3243 			imageViewMinLodExtGroup2D->addChild(imageViewMinLodGroup2D.release());
3244 			imageViewMinLodExtGroup2D->addChild(imageViewMinLodBaseLevelGroup2D.release());
3245 		}
3246 #endif // CTS_USES_VULKANSC
3247 
3248 		group2D->addChild(biasGroup2D.release());
3249 		group2D->addChild(minLodGroup2D.release());
3250 		group2D->addChild(maxLodGroup2D.release());
3251 		group2D->addChild(baseLevelGroup2D.release());
3252 		group2D->addChild(maxLevelGroup2D.release());
3253 #ifndef CTS_USES_VULKANSC
3254 		group2D->addChild(imageViewMinLodExtGroup2D.release());
3255 #endif // CTS_USES_VULKANSC
3256 
3257 		textureMipmappingTests->addChild(group2D.release());
3258 	}
3259 
3260 	// Cubemap cases.
3261 	{
3262 		de::MovePtr<tcu::TestCaseGroup>	groupCube			(new tcu::TestCaseGroup(testCtx, "cubemap", "Cube Mipmap Filtering"));
3263 
3264 		de::MovePtr<tcu::TestCaseGroup>	minLodGroupCube		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
3265 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroupCube		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
3266 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
3267 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
3268 
3269 #ifndef CTS_USES_VULKANSC
3270 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroupCube	(new tcu::TestCaseGroup(testCtx, "image_view_min_lod", "VK_EXT_image_view_min_lod tests"));
3271 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroupCube	(new tcu::TestCaseGroup(testCtx, "min_lod", "ImageView's minLod"));
3272 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroupCube	(new tcu::TestCaseGroup(testCtx, "base_level", "ImageView's minLod with base level different than one"));
3273 #endif // CTS_USES_VULKANSC
3274 
3275 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
3276 		{
3277 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup	(new tcu::TestCaseGroup(testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc));
3278 
3279 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3280 			{
3281 				for (int magFilter = 0; magFilter < DE_LENGTH_OF_ARRAY(magFilterModes); magFilter++)
3282 				{
3283 					for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3284 					{
3285 						TextureCubeMipmapTestCaseParameters	testParameters;
3286 
3287 						testParameters.coordType		= cubeCoordTypes[coordType].type;
3288 						testParameters.minFilter		= minFilterModes[minFilter].mode;
3289 						testParameters.magFilter		= magFilterModes[magFilter].mode;
3290 						testParameters.minFilterName	= minFilterModes[minFilter].name;
3291 						testParameters.wrapS			= wrapModes[wrapMode].mode;
3292 						testParameters.wrapT			= wrapModes[wrapMode].mode;
3293 						testParameters.format			= VK_FORMAT_R8G8B8A8_UNORM;
3294 						testParameters.size				= cubeMapSize;
3295 						testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3296 
3297 						if (testParameters.coordType == COORDTYPE_BASIC_BIAS)
3298 							testParameters.programs.push_back(PROGRAM_CUBE_FLOAT_BIAS);
3299 						else
3300 							testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3301 
3302 						std::ostringstream name;
3303 						name << minFilterModes[minFilter].name
3304 							 << "_" << magFilterModes[magFilter].name
3305 							 << "_" << wrapModes[wrapMode].name;
3306 
3307 						coordTypeGroup->addChild(new TextureTestCase<TextureCubeMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
3308 					}
3309 				}
3310 			}
3311 
3312 			groupCube->addChild(coordTypeGroup.release());
3313 		}
3314 
3315 		// Cubemap LOD controls.
3316 		{
3317 			// MIN_LOD
3318 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3319 			{
3320 				TextureCubeMipmapTestCaseParameters	testParameters;
3321 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3322 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3323 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3324 
3325 				minLodGroupCube->addChild(new TextureTestCase<TextureCubeMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3326 			}
3327 
3328 			// MAX_LOD
3329 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3330 			{
3331 				TextureCubeMipmapTestCaseParameters	testParameters;
3332 				testParameters.minFilter	= minFilterModes[minFilter].mode;
3333 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
3334 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3335 
3336 				maxLodGroupCube->addChild(new TextureTestCase<TextureCubeMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3337 			}
3338 		}
3339 
3340 		{
3341 			// BASE_LEVEL
3342 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3343 			{
3344 				TextureCubeMipmapTestCaseParameters	testParameters;
3345 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3346 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3347 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3348 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3349 
3350 				baseLevelGroupCube->addChild(new TextureTestCase<TextureCubeBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3351 			}
3352 
3353 			// MAX_LEVEL
3354 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3355 			{
3356 				TextureCubeMipmapTestCaseParameters	testParameters;
3357 				testParameters.minFilter		= minFilterModes[minFilter].mode;
3358 				testParameters.minFilterName	= minFilterModes[minFilter].name;
3359 				testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3360 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3361 
3362 				maxLevelGroupCube->addChild(new TextureTestCase<TextureCubeMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3363 			}
3364 		}
3365 
3366 		// Cube VK_EXT_image_view_min_lod.
3367 #ifndef CTS_USES_VULKANSC
3368 		{
3369 			// MIN_LOD
3370 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3371 			{
3372 				TextureCubeMipmapTestCaseParameters	testParameters;
3373 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3374 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3375 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3376 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3377 
3378 				imageViewMinLodGroupCube->addChild(new TextureTestCase<TextureCubeImageViewMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3379 			}
3380 
3381 			// BASE_LEVEL
3382 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3383 			{
3384 				TextureCubeMipmapTestCaseParameters	testParameters;
3385 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3386 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3387 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3388 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3389 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3390 
3391 				imageViewMinLodBaseLevelGroupCube->addChild(new TextureTestCase<TextureCubeImageViewMinLodBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3392 			}
3393 
3394 			imageViewMinLodExtGroupCube->addChild(imageViewMinLodGroupCube.release());
3395 			imageViewMinLodExtGroupCube->addChild(imageViewMinLodBaseLevelGroupCube.release());
3396 		}
3397 #endif // CTS_USES_VULKANSC
3398 
3399 		groupCube->addChild(minLodGroupCube.release());
3400 		groupCube->addChild(maxLodGroupCube.release());
3401 		groupCube->addChild(baseLevelGroupCube.release());
3402 		groupCube->addChild(maxLevelGroupCube.release());
3403 #ifndef CTS_USES_VULKANSC
3404 		groupCube->addChild(imageViewMinLodExtGroupCube.release());
3405 #endif // CTS_USES_VULKANSC
3406 
3407 		textureMipmappingTests->addChild(groupCube.release());
3408 	}
3409 
3410 	// 3D cases.
3411 	{
3412 		de::MovePtr<tcu::TestCaseGroup>	group3D				(new tcu::TestCaseGroup(testCtx, "3d", "3D Mipmap Filtering"));
3413 
3414 		de::MovePtr<tcu::TestCaseGroup>	biasGroup3D			(new tcu::TestCaseGroup(testCtx, "bias", "User-supplied bias value"));
3415 		de::MovePtr<tcu::TestCaseGroup>	minLodGroup3D		(new tcu::TestCaseGroup(testCtx, "min_lod", "Lod control: min lod"));
3416 		de::MovePtr<tcu::TestCaseGroup>	maxLodGroup3D		(new tcu::TestCaseGroup(testCtx, "max_lod", "Lod control: max lod"));
3417 		de::MovePtr<tcu::TestCaseGroup>	baseLevelGroup3D	(new tcu::TestCaseGroup(testCtx, "base_level", "Base level"));
3418 		de::MovePtr<tcu::TestCaseGroup>	maxLevelGroup3D		(new tcu::TestCaseGroup(testCtx, "max_level", "Max level"));
3419 
3420 #ifndef CTS_USES_VULKANSC
3421 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup3D	(new tcu::TestCaseGroup(testCtx, "image_view_min_lod", "VK_EXT_image_view_min_lod tests"));
3422 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup3D	(new tcu::TestCaseGroup(testCtx, "min_lod", "ImageView's minLod"));
3423 		de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup3D	(new tcu::TestCaseGroup(testCtx, "base_level", "ImageView's minLod with base level different than one"));
3424 #endif // CTS_USES_VULKANSC
3425 
3426 		for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3427 		{
3428 			de::MovePtr<tcu::TestCaseGroup>	coordTypeGroup	(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name, coordTypes[coordType].desc));
3429 
3430 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3431 			{
3432 				for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3433 				{
3434 					// Add other size variants to basic cases only.
3435 					int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
3436 
3437 					Texture3DMipmapTestCaseParameters	testParameters;
3438 
3439 					testParameters.coordType		= coordTypes[coordType].type;
3440 					testParameters.minFilter		= minFilterModes[minFilter].mode;
3441 					testParameters.minFilterName	= minFilterModes[minFilter].name;
3442 					testParameters.wrapR			= wrapModes[wrapMode].mode;
3443 					testParameters.wrapS			= wrapModes[wrapMode].mode;
3444 					testParameters.wrapT			= wrapModes[wrapMode].mode;
3445 					testParameters.format			= VK_FORMAT_R8G8B8A8_UNORM;
3446 					testParameters.aspectMask		= VK_IMAGE_ASPECT_COLOR_BIT;
3447 					testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3448 
3449 					for (int size = 0; size < sizeEnd; size++)
3450 					{
3451 						testParameters.width			= tex3DSizes[size].width;
3452 						testParameters.height			= tex3DSizes[size].height;
3453 						testParameters.depth			= tex3DSizes[size].depth;
3454 
3455 						std::ostringstream name;
3456 						name << minFilterModes[minFilter].name
3457 							 << "_" << wrapModes[wrapMode].name;
3458 
3459 						if (tex3DSizes[size].name)
3460 							name << "_" << tex3DSizes[size].name;
3461 
3462 						coordTypeGroup->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(testCtx, name.str().c_str(), "", testParameters));
3463 					}
3464 				}
3465 			}
3466 
3467 			group3D->addChild(coordTypeGroup.release());
3468 		}
3469 
3470 		// 3D bias variants.
3471 		{
3472 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3473 			{
3474 				Texture3DMipmapTestCaseParameters	testParameters;
3475 				testParameters.coordType			= COORDTYPE_BASIC_BIAS;
3476 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3477 				testParameters.wrapR				= Sampler::REPEAT_GL;
3478 				testParameters.wrapS				= Sampler::REPEAT_GL;
3479 				testParameters.wrapT				= Sampler::REPEAT_GL;
3480 				testParameters.format				= VK_FORMAT_R8G8B8A8_UNORM;
3481 				testParameters.width				= tex3DSizes[0].width;
3482 				testParameters.height				= tex3DSizes[0].height;
3483 				testParameters.depth				= tex3DSizes[0].depth;
3484 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3485 				testParameters.programs.push_back(PROGRAM_3D_FLOAT_BIAS);
3486 
3487 				biasGroup3D->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3488 			}
3489 		}
3490 
3491 		// 3D LOD controls.
3492 		{
3493 			// MIN_LOD
3494 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3495 			{
3496 				Texture3DMipmapTestCaseParameters	testParameters;
3497 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3498 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3499 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3500 
3501 				minLodGroup3D->addChild(new TextureTestCase<Texture3DMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3502 			}
3503 
3504 			// MAX_LOD
3505 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3506 			{
3507 				Texture3DMipmapTestCaseParameters	testParameters;
3508 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3509 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3510 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3511 
3512 				maxLodGroup3D->addChild(new TextureTestCase<Texture3DMaxLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3513 			}
3514 		}
3515 
3516 		{
3517 			// BASE_LEVEL
3518 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3519 			{
3520 				Texture3DMipmapTestCaseParameters	testParameters;
3521 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3522 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3523 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3524 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3525 
3526 				baseLevelGroup3D->addChild(new TextureTestCase<Texture3DBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3527 			}
3528 
3529 			// MAX_LEVEL
3530 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3531 			{
3532 				Texture3DMipmapTestCaseParameters	testParameters;
3533 				testParameters.minFilter			= minFilterModes[minFilter].mode;
3534 				testParameters.minFilterName		= minFilterModes[minFilter].name;
3535 				testParameters.aspectMask			= VK_IMAGE_ASPECT_COLOR_BIT;
3536 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3537 
3538 				maxLevelGroup3D->addChild(new TextureTestCase<Texture3DMaxLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3539 			}
3540 		}
3541 
3542 		// 3D VK_EXT_image_view_min_lod.
3543 #ifndef CTS_USES_VULKANSC
3544 		{
3545 			// MIN_LOD
3546 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3547 			{
3548 				Texture3DMipmapTestCaseParameters	testParameters;
3549 				testParameters.minFilter				= minFilterModes[minFilter].mode;
3550 				testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
3551 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3552 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3553 
3554 				imageViewMinLodGroup3D->addChild(new TextureTestCase<Texture3DImageViewMinLodTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3555 
3556 				std::ostringstream name;
3557 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3558 				testParameters.testType				= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3559 				imageViewMinLodGroup3D->addChild(new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), "", testParameters));
3560 			}
3561 
3562 			// BASE_LEVEL
3563 			for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3564 			{
3565 				Texture3DMipmapTestCaseParameters testParameters;
3566 				testParameters.minFilter				= minFilterModes[minFilter].mode;
3567 				testParameters.minFilterName			= minFilterModes[minFilter].name;
3568 				testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
3569 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3570 				testParameters.testType					= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3571 
3572 
3573 				imageViewMinLodBaseLevelGroup3D->addChild(new TextureTestCase<Texture3DImageViewMinLodBaseLevelTestInstance>(testCtx, minFilterModes[minFilter].name, "", testParameters));
3574 
3575 				std::ostringstream name;
3576 				name << minFilterModes[minFilter].name << "_integer_texel_coord";
3577 				testParameters.testType					= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3578 				imageViewMinLodBaseLevelGroup3D->addChild(new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), "", testParameters));
3579 			}
3580 
3581 			imageViewMinLodExtGroup3D->addChild(imageViewMinLodGroup3D.release());
3582 			imageViewMinLodExtGroup3D->addChild(imageViewMinLodBaseLevelGroup3D.release());
3583 		}
3584 #endif // CTS_USES_VULKANSC
3585 
3586 		group3D->addChild(biasGroup3D.release());
3587 		group3D->addChild(minLodGroup3D.release());
3588 		group3D->addChild(maxLodGroup3D.release());
3589 		group3D->addChild(baseLevelGroup3D.release());
3590 		group3D->addChild(maxLevelGroup3D.release());
3591 #ifndef CTS_USES_VULKANSC
3592 		group3D->addChild(imageViewMinLodExtGroup3D.release());
3593 #endif // CTS_USES_VULKANSC
3594 
3595 		textureMipmappingTests->addChild(group3D.release());
3596 	}
3597 
3598 #ifndef CTS_USES_VULKANSC
3599 	{
3600 		const auto minLodGatherGroup = createTestGroup(testCtx, "min_lod_gather", "Test minLod with textureGather operations", populateMinLodGatherGroup, destroyDeviceHelpers);
3601 		textureMipmappingTests->addChild(minLodGatherGroup);
3602 	}
3603 #endif // CTS_USES_VULKANSC
3604 }
3605 
createTextureMipmappingTests(tcu::TestContext & testCtx)3606 tcu::TestCaseGroup* createTextureMipmappingTests (tcu::TestContext& testCtx)
3607 {
3608 	return createTestGroup(testCtx, "mipmap", "Texture mipmapping tests.", populateTextureMipmappingTests);
3609 }
3610 
3611 } // texture
3612 } // vkt
3613