• 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 (c) 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 Texture filtering tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuVectorUtil.hpp"
27 #include "tcuTexVerifierUtil.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestCaseUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 #include "vktTextureFilteringTests.hpp"
37 #include "vktTextureTestUtil.hpp"
38 #include <string>
39 #include <vector>
40 
41 using namespace vk;
42 
43 namespace vkt
44 {
45 namespace texture
46 {
47 namespace util
48 {
49 
50 template <>
checkTextureSupport(Context & context,const Texture2DTestCaseParameters & testParameters)51 void checkTextureSupport (Context& context, const Texture2DTestCaseParameters& testParameters)
52 {
53 	if (testParameters.minFilter == tcu::Sampler::Sampler::CUBIC || testParameters.minFilter == tcu::Sampler::Sampler::CUBIC_MIPMAP_NEAREST || testParameters.minFilter == tcu::Sampler::Sampler::CUBIC_MIPMAP_LINEAR ||
54 		testParameters.magFilter == tcu::Sampler::Sampler::CUBIC)
55 	{
56 		context.requireDeviceFunctionality("VK_EXT_filter_cubic");
57 
58 		// check if image format supports cubic filtering
59 		const vk::VkPhysicalDeviceImageViewImageFormatInfoEXT imageViewImageFormatInfo =
60 		{
61 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT,		// VkStructureType    sType;
62 			DE_NULL,																// void*              pNext;
63 			VK_IMAGE_VIEW_TYPE_2D													// VkImageViewType    imageViewType;
64 		};
65 
66 		const vk::VkPhysicalDeviceImageFormatInfo2 formatInfo =
67 		{
68 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,					// VkStructureType       sType;
69 			&imageViewImageFormatInfo,												// const void*           pNext;
70 			testParameters.format,													// VkFormat              format;
71 			VK_IMAGE_TYPE_2D,														// VkImageType           type;
72 			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling         tiling;
73 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
74 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
75 			VK_IMAGE_USAGE_TRANSFER_DST_BIT,										// VkImageUsageFlags     usage;
76 			0u																		// VkImageCreateFlags    flags;
77 		};
78 
79 		vk::VkFilterCubicImageViewImageFormatPropertiesEXT cubicImageViewProperties =
80 		{
81 			VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT,	// VkStructureType	sType;
82 			DE_NULL,																// void*			pNext;
83 			DE_FALSE,																// VkBool32		filterCubic;
84 			DE_FALSE																// VkBool32		filterCubicMinmax;
85 		};
86 
87 		vk::VkImageFormatProperties2 formatProperties =
88 		{
89 			VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,							// VkStructureType			sType;
90 			&cubicImageViewProperties,												// void*					pNext;
91 			vk::VkImageFormatProperties()											// VkImageFormatProperties	imageFormatProperties;
92 		};
93 
94 		const vk::VkResult res = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &formatInfo, &formatProperties);
95 		if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
96 			TCU_THROW(NotSupportedError, "Image format not supported");
97 		VK_CHECK(res);
98 
99 		if (!cubicImageViewProperties.filterCubic)
100 			TCU_THROW(NotSupportedError, "Image format does not support cubic filtering");
101 
102 		VkFormatProperties formatProps;
103 		context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), testParameters.format, &formatProps);
104 		if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT) == 0)
105 			TCU_THROW(NotSupportedError, "Format properties do not support cubic filtering feature");
106 	}
107 
108 	if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE || testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
109 		context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
110 }
111 
112 template <>
checkTextureSupport(Context & context,const TextureCubeTestCaseParameters & testParameters)113 void checkTextureSupport (Context& context, const TextureCubeTestCaseParameters& testParameters)
114 {
115 	if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE || testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
116 		context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
117 }
118 
119 template <>
checkTextureSupport(Context & context,const Texture2DArrayTestCaseParameters & testParameters)120 void checkTextureSupport (Context& context, const Texture2DArrayTestCaseParameters& testParameters)
121 {
122 	if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE || testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
123 		context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
124 }
125 
126 template <>
checkTextureSupport(Context & context,const Texture3DTestCaseParameters & testParameters)127 void checkTextureSupport (Context& context, const Texture3DTestCaseParameters& testParameters)
128 {
129 	if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE || testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE || testParameters.wrapR == tcu::Sampler::Sampler::MIRRORED_ONCE)
130 		context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
131 }
132 
133 } // util
134 
135 namespace
136 {
137 
138 using std::vector;
139 using std::string;
140 using tcu::TestLog;
141 using tcu::Sampler;
142 
143 using namespace texture::util;
144 using namespace glu::TextureTestUtil;
145 
146 enum
147 {
148 	TEXCUBE_VIEWPORT_SIZE		= 28,
149 
150 	TEX2D_VIEWPORT_WIDTH		= 64,
151 	TEX2D_VIEWPORT_HEIGHT		= 64,
152 
153 	TEX3D_VIEWPORT_WIDTH		= 64,
154 	TEX3D_VIEWPORT_HEIGHT		= 64,
155 };
156 
157 class Texture2DFilteringTestInstance : public TestInstance
158 {
159 public:
160 	typedef Texture2DTestCaseParameters	ParameterType;
161 
162 										Texture2DFilteringTestInstance		(Context& context, const ParameterType& testParameters);
163 										~Texture2DFilteringTestInstance		(void);
164 
165 	virtual tcu::TestStatus				iterate								(void);
166 private:
167 										Texture2DFilteringTestInstance		(const Texture2DFilteringTestInstance& other);
168 	Texture2DFilteringTestInstance&		operator=							(const Texture2DFilteringTestInstance& other);
169 
170 	struct FilterCase
171 	{
172 		int						textureIndex;
173 
174 		tcu::Vec2				minCoord;
175 		tcu::Vec2				maxCoord;
176 
FilterCasevkt::texture::__anon3d42235c0111::Texture2DFilteringTestInstance::FilterCase177 		FilterCase (void)
178 			: textureIndex(-1)
179 		{
180 		}
181 
FilterCasevkt::texture::__anon3d42235c0111::Texture2DFilteringTestInstance::FilterCase182 		FilterCase (int tex_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
183 			: textureIndex	(tex_)
184 			, minCoord		(minCoord_)
185 			, maxCoord		(maxCoord_)
186 		{
187 		}
188 	};
189 
190 	const ParameterType			m_testParameters;
191 	vector<TestTexture2DSp>		m_textures;
192 	vector<FilterCase>			m_cases;
193 	TextureRenderer				m_renderer;
194 	int							m_caseNdx;
195 };
196 
Texture2DFilteringTestInstance(Context & context,const ParameterType & testParameters)197 Texture2DFilteringTestInstance::Texture2DFilteringTestInstance (Context& context, const ParameterType& testParameters)
198 	: TestInstance			(context)
199 	, m_testParameters		(testParameters)
200 	, m_renderer			(context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
201 	, m_caseNdx				(0)
202 {
203 	const bool						mipmaps		= m_testParameters.mipmaps;
204 	const int						numLevels	= mipmaps ? deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1 : 1;
205 	const tcu::TextureFormat		texFormat	= vk::mapVkFormat(m_testParameters.format);
206 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
207 	tcu::Vec4						cBias, cScale;
208 	if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
209 	{
210 		const tcu::TextureFormat		texFormatStencil	= vk::mapVkFormat(VK_FORMAT_S8_UINT);
211 		const tcu::TextureFormatInfo	fmtInfoStencil		= tcu::getTextureFormatInfo(texFormatStencil);
212 		cBias												= fmtInfoStencil.valueMin;
213 		cScale												= fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
214 	}
215 	else
216 	{
217 		cBias												= fmtInfo.valueMin;
218 		cScale												= fmtInfo.valueMax - fmtInfo.valueMin;
219 	}
220 
221 	// Create 2 textures.
222 	m_textures.reserve(2);
223 	for (int ndx = 0; ndx < 2; ndx++)
224 		if (mipmaps)
225 			m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
226 		else
227 			m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, 1)));
228 
229 	// Fill first gradient texture.
230 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
231 	{
232 		const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
233 		const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
234 
235 		if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
236 			tcu::fillWithComponentGradients(getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), gMin, gMax);
237 		else
238 			tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
239 	}
240 
241 	// Fill second with grid texture.
242 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
243 	{
244 		const deUint32	step	= 0x00ffffff / numLevels;
245 		const deUint32	rgb		= step*levelNdx;
246 		const deUint32	colorA	= 0xff000000 | rgb;
247 		const deUint32	colorB	= 0xff000000 | ~rgb;
248 
249 		if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
250 			tcu::fillWithGrid(getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
251 		else
252 			tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
253 	}
254 
255 	// Upload.
256 	for (vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
257 	{
258 		m_renderer.add2DTexture(*i, testParameters.aspectMask);
259 	}
260 
261 	// Compute cases.
262 	{
263 		const struct
264 		{
265 			const int		texNdx;
266 			const float		lodX;
267 			const float		lodY;
268 			const float		oX;
269 			const float		oY;
270 		} cases[] =
271 		{
272 			{ 0,	1.6f,	2.9f,	-1.0f,	-2.7f	},
273 			{ 0,	-2.0f,	-1.35f,	-0.2f,	0.7f	},
274 			{ 1,	0.14f,	0.275f,	-1.5f,	-1.1f	},
275 			{ 1,	-0.92f,	-2.64f,	0.4f,	-0.1f	},
276 		};
277 
278 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
279 		{
280 			const int	texNdx	= de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
281 			const float	lodX	= cases[caseNdx].lodX;
282 			const float	lodY	= cases[caseNdx].lodY;
283 			const float	oX		= cases[caseNdx].oX;
284 			const float	oY		= cases[caseNdx].oY;
285 			const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
286 			const float	sY		= deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[texNdx]->getTexture().getHeight());
287 
288 			m_cases.push_back(FilterCase(texNdx, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
289 		}
290 	}
291 }
292 
~Texture2DFilteringTestInstance(void)293 Texture2DFilteringTestInstance::~Texture2DFilteringTestInstance (void)
294 {
295 }
296 
iterate(void)297 tcu::TestStatus Texture2DFilteringTestInstance::iterate (void)
298 {
299 	tcu::TestLog&					log			= m_context.getTestContext().getLog();
300 	const pipeline::TestTexture2D&	texture		= m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
301 	const tcu::TextureFormat		texFmt		= texture.getTextureFormat();
302 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFmt);
303 	const FilterCase&				curCase		= m_cases[m_caseNdx];
304 	ReferenceParams					refParams	(TEXTURETYPE_2D);
305 	tcu::Surface					rendered	(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
306 	vector<float>					texCoord;
307 
308 	// Setup params for reference.
309 
310 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter, !m_testParameters.unnormal);
311 	if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
312 	{
313 		refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
314 		refParams.samplerType = SAMPLERTYPE_UINT;
315 	}
316 	else
317 		refParams.samplerType = getSamplerType(texFmt);
318 	refParams.colorBias		= fmtInfo.lookupBias;
319 	refParams.colorScale	= fmtInfo.lookupScale;
320 	refParams.unnormal		= m_testParameters.unnormal;
321 
322 	// Compute texture coordinates.
323 	log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
324 	computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
325 
326 	m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
327 
328 	{
329 		const bool				isNearestOnly	= m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
330 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
331 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
332 		const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
333 		tcu::LodPrecision		lodPrecision;
334 		tcu::LookupPrecision	lookupPrecision;
335 
336 		lodPrecision.derivateBits		= 18;
337 		lodPrecision.lodBits			= 6;
338 		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
339 		lookupPrecision.coordBits		= tcu::IVec3(20,20,0);
340 		lookupPrecision.uvwBits			= tcu::IVec3(7,7,0);
341 		lookupPrecision.colorMask		= getCompareMask(pixelFormat);
342 
343 		const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DView)texture.getTexture(),
344 													   &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
345 
346 		if (!isHighQuality)
347 		{
348 			// Evaluate against lower precision requirements.
349 			lodPrecision.lodBits	= 4;
350 			lookupPrecision.uvwBits	= tcu::IVec3(4,4,0);
351 
352 			log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
353 
354 			const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DView)texture.getTexture(),
355 												  &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
356 
357 			if (!isOk)
358 			{
359 				log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
360 				return tcu::TestStatus::fail("Image verification failed");
361 			}
362 		}
363 	}
364 
365 	m_caseNdx += 1;
366 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
367 }
368 
369 struct TextureCubeFilteringTestCaseParameters : public TextureCubeTestCaseParameters
370 {
371 	bool	onlySampleFaceInterior;
372 };
373 
374 class TextureCubeFilteringTestInstance : public TestInstance
375 {
376 public:
377 	typedef TextureCubeFilteringTestCaseParameters	ParameterType;
378 
379 													TextureCubeFilteringTestInstance	(Context& context, const ParameterType& testParameters);
380 													~TextureCubeFilteringTestInstance	(void);
381 
382 	virtual tcu::TestStatus							iterate								(void);
383 
384 private:
385 													TextureCubeFilteringTestInstance	(const TextureCubeFilteringTestInstance& other);
386 	TextureCubeFilteringTestInstance&				operator=							(const TextureCubeFilteringTestInstance& other);
387 
388 	struct FilterCase
389 	{
390 		int						textureIndex;
391 		tcu::Vec2				bottomLeft;
392 		tcu::Vec2				topRight;
393 
FilterCasevkt::texture::__anon3d42235c0111::TextureCubeFilteringTestInstance::FilterCase394 		FilterCase (void)
395 			: textureIndex(-1)
396 		{
397 		}
398 
FilterCasevkt::texture::__anon3d42235c0111::TextureCubeFilteringTestInstance::FilterCase399 		FilterCase (int tex_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
400 			: textureIndex	(tex_)
401 			, bottomLeft	(bottomLeft_)
402 			, topRight		(topRight_)
403 		{
404 		}
405 	};
406 
407 	const ParameterType			m_testParameters;
408 	vector<TestTextureCubeSp>	m_textures;
409 	vector<FilterCase>			m_cases;
410 	TextureRenderer				m_renderer;
411 	int							m_caseNdx;
412 };
413 
TextureCubeFilteringTestInstance(Context & context,const ParameterType & testParameters)414 TextureCubeFilteringTestInstance::TextureCubeFilteringTestInstance (Context& context, const ParameterType& testParameters)
415 	: TestInstance			(context)
416 	, m_testParameters		(testParameters)
417 	, m_renderer			(context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
418 	, m_caseNdx				(0)
419 {
420 	const int						numLevels	= deLog2Floor32(m_testParameters.size)+1;
421 	const tcu::TextureFormat		texFormat	= vk::mapVkFormat(m_testParameters.format);
422 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
423 	tcu::Vec4						cBias, cScale;
424 	if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
425 	{
426 		const tcu::TextureFormat		texFormatStencil	= vk::mapVkFormat(VK_FORMAT_S8_UINT);
427 		const tcu::TextureFormatInfo	fmtInfoStencil		= tcu::getTextureFormatInfo(texFormatStencil);
428 		cBias												= fmtInfoStencil.valueMin;
429 		cScale												= fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
430 	}
431 	else
432 	{
433 		cBias												= fmtInfo.valueMin;
434 		cScale												= fmtInfo.valueMax - fmtInfo.valueMin;
435 	}
436 
437 	m_textures.reserve(2);
438 	for (int ndx = 0; ndx < 2; ndx++)
439 		m_textures.push_back(TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
440 
441 	// Fill first with gradient texture.
442 	static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
443 	{
444 		{ tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
445 		{ tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
446 		{ tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
447 		{ tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
448 		{ tcu::Vec4(0.0f, 0.0f, 0.0f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
449 		{ tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
450 	};
451 
452 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
453 	{
454 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
455 		{
456 			if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
457 				tcu::fillWithComponentGradients(getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, face), tcu::Sampler::MODE_STENCIL), gradients[face][0] * cScale + cBias, gradients[face][1] * cScale + cBias);
458 			else
459 				tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face), gradients[face][0] * cScale + cBias, gradients[face][1] * cScale + cBias);
460 		}
461 	}
462 
463 	// Fill second with grid texture.
464 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
465 	{
466 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
467 		{
468 			const deUint32	step	= 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
469 			const deUint32	rgb		= step*levelNdx*face;
470 			const deUint32	colorA	= 0xff000000 | rgb;
471 			const deUint32	colorB	= 0xff000000 | ~rgb;
472 
473 			tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
474 
475 			if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
476 				tcu::fillWithGrid(getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, face), tcu::Sampler::MODE_STENCIL), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
477 			else
478 				tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
479 		}
480 	}
481 
482 	// Upload.
483 	for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
484 	{
485 		m_renderer.addCubeTexture(*i, testParameters.aspectMask);
486 	}
487 
488 	// Compute cases
489 	{
490 		const int tex0	= 0;
491 		const int tex1	= m_textures.size() > 1 ? 1 : 0;
492 
493 		if (m_testParameters.onlySampleFaceInterior)
494 		{
495 			m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f,  0.8f)));	// minification
496 			m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f,  0.8f)));	// magnification
497 			m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f,  0.8f)));	// minification
498 			m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f), tcu::Vec2(0.6f,  0.5f)));		// magnification
499 		}
500 		else
501 		{
502 			m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f)));	// minification
503 
504 			m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f), tcu::Vec2(1.25f, 1.20f)));	// magnification
505 			m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f)));	// minification
506 			m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f), tcu::Vec2(-0.8f, -0.8f)));	// magnification
507 		}
508 	}
509 }
510 
~TextureCubeFilteringTestInstance(void)511 TextureCubeFilteringTestInstance::~TextureCubeFilteringTestInstance (void)
512 {
513 }
514 
getFaceDesc(const tcu::CubeFace face)515 const char* getFaceDesc (const tcu::CubeFace face)
516 {
517 	switch (face)
518 	{
519 		case tcu::CUBEFACE_NEGATIVE_X:	return "-X";
520 		case tcu::CUBEFACE_POSITIVE_X:	return "+X";
521 		case tcu::CUBEFACE_NEGATIVE_Y:	return "-Y";
522 		case tcu::CUBEFACE_POSITIVE_Y:	return "+Y";
523 		case tcu::CUBEFACE_NEGATIVE_Z:	return "-Z";
524 		case tcu::CUBEFACE_POSITIVE_Z:	return "+Z";
525 		default:
526 			DE_ASSERT(false);
527 			return DE_NULL;
528 	}
529 }
530 
iterate(void)531 tcu::TestStatus TextureCubeFilteringTestInstance::iterate (void)
532 {
533 	tcu::TestLog&						log			= m_context.getTestContext().getLog();
534 
535 	const pipeline::TestTextureCube&	texture		= m_renderer.getCubeTexture(m_cases[m_caseNdx].textureIndex);
536 	const tcu::TextureFormat			texFmt		= texture.getTextureFormat();
537 	const tcu::TextureFormatInfo		fmtInfo		= tcu::getTextureFormatInfo(texFmt);
538 	const FilterCase&					curCase		= m_cases[m_caseNdx];
539 	ReferenceParams						refParams	(TEXTURETYPE_CUBE);
540 
541 	// Params for reference computation.
542 	refParams.sampler					= util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
543 	if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
544 	{
545 		refParams.sampler.depthStencilMode	= tcu::Sampler::MODE_STENCIL;
546 		refParams.samplerType				= SAMPLERTYPE_UINT;
547 	}
548 	else
549 		refParams.samplerType				= getSamplerType(texFmt);
550 	refParams.sampler.seamlessCubeMap	= true;
551 	refParams.lodMode					= LODMODE_EXACT;
552 	refParams.colorBias					= fmtInfo.lookupBias;
553 	refParams.colorScale				= fmtInfo.lookupScale;
554 
555 	log << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight << TestLog::EndMessage;
556 
557 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
558 	{
559 		const tcu::CubeFace		face		= tcu::CubeFace(faceNdx);
560 		tcu::Surface			rendered	(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
561 		vector<float>			texCoord;
562 
563 		computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
564 
565 		log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
566 
567 		// \todo Log texture coordinates.
568 
569 		m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
570 
571 		{
572 			const bool				isNearestOnly	= m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
573 			const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
574 			const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
575 			const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
576 			tcu::LodPrecision		lodPrecision;
577 			tcu::LookupPrecision	lookupPrecision;
578 
579 			lodPrecision.derivateBits		= 10;
580 			lodPrecision.lodBits			= 5;
581 			lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
582 			lookupPrecision.coordBits		= tcu::IVec3(10,10,10);
583 			lookupPrecision.uvwBits			= tcu::IVec3(6,6,0);
584 			lookupPrecision.colorMask		= getCompareMask(pixelFormat);
585 
586 			const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::TextureCubeView)texture.getTexture(),
587 														   &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
588 
589 			if (!isHighQuality)
590 			{
591 				// Evaluate against lower precision requirements.
592 				lodPrecision.lodBits	= 4;
593 				lookupPrecision.uvwBits	= tcu::IVec3(4,4,0);
594 
595 				log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
596 
597 				const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::TextureCubeView)texture.getTexture(),
598 													  &texCoord[0], refParams, lookupPrecision, lodPrecision, pixelFormat);
599 
600 				if (!isOk)
601 				{
602 					log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
603 					return tcu::TestStatus::fail("Image verification failed");
604 				}
605 			}
606 		}
607 	}
608 
609 	m_caseNdx += 1;
610 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
611 }
612 
613 // 2D array filtering
614 
615 class Texture2DArrayFilteringTestInstance : public TestInstance
616 {
617 public:
618 	typedef Texture2DArrayTestCaseParameters	ParameterType;
619 
620 												Texture2DArrayFilteringTestInstance		(Context& context, const ParameterType& testParameters);
621 												~Texture2DArrayFilteringTestInstance	(void);
622 
623 	virtual tcu::TestStatus						iterate									(void);
624 
625 private:
626 												Texture2DArrayFilteringTestInstance		(const Texture2DArrayFilteringTestInstance&);
627 	Texture2DArrayFilteringTestInstance&		operator=								(const Texture2DArrayFilteringTestInstance&);
628 
629 	struct FilterCase
630 	{
631 		int							textureIndex;
632 		tcu::Vec2					lod;
633 		tcu::Vec2					offset;
634 		tcu::Vec2					layerRange;
635 
FilterCasevkt::texture::__anon3d42235c0111::Texture2DArrayFilteringTestInstance::FilterCase636 		FilterCase (void)
637 			: textureIndex(-1)
638 		{
639 		}
640 
FilterCasevkt::texture::__anon3d42235c0111::Texture2DArrayFilteringTestInstance::FilterCase641 		FilterCase (const int tex_, const tcu::Vec2& lod_, const tcu::Vec2& offset_, const tcu::Vec2& layerRange_)
642 			: textureIndex	(tex_)
643 			, lod			(lod_)
644 			, offset		(offset_)
645 			, layerRange	(layerRange_)
646 		{
647 		}
648 	};
649 
650 	const ParameterType				m_testParameters;
651 	vector<TestTexture2DArraySp>	m_textures;
652 	vector<FilterCase>				m_cases;
653 	TextureRenderer					m_renderer;
654 	int								m_caseNdx;
655 };
656 
Texture2DArrayFilteringTestInstance(Context & context,const ParameterType & testParameters)657 Texture2DArrayFilteringTestInstance::Texture2DArrayFilteringTestInstance (Context& context, const ParameterType& testParameters)
658 	: TestInstance			(context)
659 	, m_testParameters		(testParameters)
660 	, m_renderer			(context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
661 	, m_caseNdx				(0)
662 {
663 	const int						numLevels	= deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
664 	const tcu::TextureFormat		texFormat	= vk::mapVkFormat(m_testParameters.format);
665 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
666 	tcu::Vec4						cBias, cScale;
667 	if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
668 	{
669 		const tcu::TextureFormat		texFormatStencil	= vk::mapVkFormat(VK_FORMAT_S8_UINT);
670 		const tcu::TextureFormatInfo	fmtInfoStencil		= tcu::getTextureFormatInfo(texFormatStencil);
671 		cBias												= fmtInfoStencil.valueMin;
672 		cScale												= fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
673 	}
674 	else
675 	{
676 		cBias												= fmtInfo.valueMin;
677 		cScale												= fmtInfo.valueMax - fmtInfo.valueMin;
678 	}
679 
680 	// Create textures.
681 	m_textures.reserve(2);
682 	for (int ndx = 0; ndx < 2; ndx++)
683 		m_textures.push_back(TestTexture2DArraySp(new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.numLayers)));
684 
685 	const tcu::IVec4 levelSwz[] =
686 	{
687 		tcu::IVec4(0,1,2,3),
688 		tcu::IVec4(2,1,3,0),
689 		tcu::IVec4(3,0,1,2),
690 		tcu::IVec4(1,3,2,0),
691 	};
692 
693 	// Fill first gradient texture (gradient direction varies between layers).
694 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
695 	{
696 		for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
697 		{
698 			const tcu::IVec4	swz		= levelSwz[layerNdx%DE_LENGTH_OF_ARRAY(levelSwz)];
699 			const tcu::Vec4		gMin	= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
700 			const tcu::Vec4		gMax	= tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
701 
702 			if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
703 				tcu::fillWithComponentGradients(getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, layerNdx), tcu::Sampler::MODE_STENCIL), gMin, gMax);
704 			else
705 				tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, layerNdx), gMin, gMax);
706 		}
707 	}
708 
709 	// Fill second with grid texture (each layer has unique colors).
710 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
711 	{
712 		for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
713 		{
714 			const deUint32	step	= 0x00ffffff / (numLevels*m_testParameters.numLayers - 1);
715 			const deUint32	rgb		= step * (levelNdx + layerNdx*numLevels);
716 			const deUint32	colorA	= 0xff000000 | rgb;
717 			const deUint32	colorB	= 0xff000000 | ~rgb;
718 
719 			if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
720 				tcu::fillWithGrid(getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, layerNdx), tcu::Sampler::MODE_STENCIL), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
721 			else
722 				tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, layerNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
723 		}
724 	}
725 
726 	// Upload.
727 	for (vector<TestTexture2DArraySp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
728 	{
729 		m_renderer.add2DArrayTexture(*i, testParameters.aspectMask);
730 	}
731 
732 	// Test cases
733 	m_cases.push_back(FilterCase(0,	tcu::Vec2( 1.5f,  2.8f  ),	tcu::Vec2(-1.0f, -2.7f), tcu::Vec2(-0.5f, float(m_testParameters.numLayers)+0.5f)));
734 	m_cases.push_back(FilterCase(1,	tcu::Vec2( 0.2f,  0.175f),	tcu::Vec2(-2.0f, -3.7f), tcu::Vec2(-0.5f, float(m_testParameters.numLayers)+0.5f)));
735 	m_cases.push_back(FilterCase(1,	tcu::Vec2(-0.8f, -2.3f  ),	tcu::Vec2( 0.2f, -0.1f), tcu::Vec2(float(m_testParameters.numLayers)+0.5f, -0.5f)));
736 	m_cases.push_back(FilterCase(0,	tcu::Vec2(-2.0f, -1.5f  ),	tcu::Vec2(-0.1f,  0.9f), tcu::Vec2(1.50001f, 1.49999f)));
737 }
738 
~Texture2DArrayFilteringTestInstance(void)739 Texture2DArrayFilteringTestInstance::~Texture2DArrayFilteringTestInstance (void)
740 {
741 }
742 
iterate(void)743 tcu::TestStatus Texture2DArrayFilteringTestInstance::iterate (void)
744 {
745 	tcu::TestLog&						log			= m_context.getTestContext().getLog();
746 
747 	const FilterCase&					curCase		= m_cases[m_caseNdx];
748 	const pipeline::TestTexture2DArray&	texture		= m_renderer.get2DArrayTexture(curCase.textureIndex);
749 	const tcu::TextureFormat			texFmt		= texture.getTextureFormat();
750 	const tcu::TextureFormatInfo		fmtInfo		= tcu::getTextureFormatInfo(texFmt);
751 	ReferenceParams						refParams	(TEXTURETYPE_2D_ARRAY);
752 	tcu::Surface						rendered	(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
753 	tcu::Vec3							texCoord[4];
754 	const float* const					texCoordPtr	= (const float*)&texCoord[0];
755 
756 	// Params for reference computation.
757 
758 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
759 	if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
760 	{
761 		refParams.sampler.depthStencilMode	= tcu::Sampler::MODE_STENCIL;
762 		refParams.samplerType				= SAMPLERTYPE_UINT;
763 	}
764 	else
765 		refParams.samplerType				= getSamplerType(texFmt);
766 	refParams.lodMode		= LODMODE_EXACT;
767 	refParams.colorBias		= fmtInfo.lookupBias;
768 	refParams.colorScale	= fmtInfo.lookupScale;
769 
770 	// Compute texture coordinates.
771 	log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset << TestLog::EndMessage;
772 
773 	{
774 		const float	lodX	= curCase.lod.x();
775 		const float	lodY	= curCase.lod.y();
776 		const float	oX		= curCase.offset.x();
777 		const float	oY		= curCase.offset.y();
778 		const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
779 		const float	sY		= deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
780 		const float	l0		= curCase.layerRange.x();
781 		const float	l1		= curCase.layerRange.y();
782 
783 		texCoord[0] = tcu::Vec3(oX,		oY,		l0);
784 		texCoord[1] = tcu::Vec3(oX,		oY+sY,	l0*0.5f + l1*0.5f);
785 		texCoord[2] = tcu::Vec3(oX+sX,	oY,		l0*0.5f + l1*0.5f);
786 		texCoord[3] = tcu::Vec3(oX+sX,	oY+sY,	l1);
787 	}
788 
789 	m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
790 
791 	{
792 
793 		const bool				isNearestOnly	= m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
794 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
795 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
796 		const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
797 		tcu::LodPrecision		lodPrecision;
798 		tcu::LookupPrecision	lookupPrecision;
799 
800 		lodPrecision.derivateBits		= 18;
801 		lodPrecision.lodBits			= 6;
802 		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
803 		lookupPrecision.coordBits		= tcu::IVec3(20,20,20);
804 		lookupPrecision.uvwBits			= tcu::IVec3(7,7,0);
805 		lookupPrecision.colorMask		= getCompareMask(pixelFormat);
806 
807 		const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DArrayView)texture.getTexture(),
808 													   texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
809 
810 		if (!isHighQuality)
811 		{
812 			// Evaluate against lower precision requirements.
813 			lodPrecision.lodBits	= 4;
814 			lookupPrecision.uvwBits	= tcu::IVec3(4,4,0);
815 
816 			log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
817 
818 			const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture2DArrayView)texture.getTexture(),
819 												  texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
820 
821 			if (!isOk)
822 			{
823 				log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
824 				return tcu::TestStatus::fail("Image verification failed");
825 			}
826 		}
827 	}
828 
829 	m_caseNdx += 1;
830 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
831 }
832 
833 // 3D filtering
834 
835 class Texture3DFilteringTestInstance : public TestInstance
836 {
837 public:
838 	typedef Texture3DTestCaseParameters	ParameterType;
839 
840 										Texture3DFilteringTestInstance		(Context& context, const ParameterType& testParameters);
841 										~Texture3DFilteringTestInstance		(void);
842 
843 	virtual tcu::TestStatus				iterate								(void);
844 
845 private:
846 										Texture3DFilteringTestInstance		(const Texture3DFilteringTestInstance& other);
847 	Texture3DFilteringTestInstance&		operator=							(const Texture3DFilteringTestInstance& other);
848 
849 	struct FilterCase
850 	{
851 		int						textureIndex;
852 		tcu::Vec3				lod;
853 		tcu::Vec3				offset;
854 
FilterCasevkt::texture::__anon3d42235c0111::Texture3DFilteringTestInstance::FilterCase855 		FilterCase (void)
856 			: textureIndex(-1)
857 		{
858 		}
859 
FilterCasevkt::texture::__anon3d42235c0111::Texture3DFilteringTestInstance::FilterCase860 		FilterCase (const int tex_, const tcu::Vec3& lod_, const tcu::Vec3& offset_)
861 			: textureIndex	(tex_)
862 			, lod			(lod_)
863 			, offset		(offset_)
864 		{
865 		}
866 	};
867 
868 	const ParameterType			m_testParameters;
869 	vector<TestTexture3DSp>		m_textures;
870 	vector<FilterCase>			m_cases;
871 	TextureRenderer				m_renderer;
872 	int							m_caseNdx;
873 };
874 
Texture3DFilteringTestInstance(Context & context,const ParameterType & testParameters)875 Texture3DFilteringTestInstance::Texture3DFilteringTestInstance (Context& context, const ParameterType& testParameters)
876 	: TestInstance			(context)
877 	, m_testParameters		(testParameters)
878 	, m_renderer			(context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
879 	, m_caseNdx				(0)
880 {
881 	const int						numLevels	= deLog2Floor32(de::max(de::max(m_testParameters.width, m_testParameters.height), m_testParameters.depth)) + 1;
882 	const tcu::TextureFormat		texFormat	= vk::mapVkFormat(m_testParameters.format);
883 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFormat);
884 	tcu::Vec4						cBias, cScale;
885 	if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
886 	{
887 		const tcu::TextureFormat		texFormatStencil	= vk::mapVkFormat(VK_FORMAT_S8_UINT);
888 		const tcu::TextureFormatInfo	fmtInfoStencil		= tcu::getTextureFormatInfo(texFormatStencil);
889 		cBias												= fmtInfoStencil.valueMin;
890 		cScale												= fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
891 	}
892 	else
893 	{
894 		cBias												= fmtInfo.valueMin;
895 		cScale												= fmtInfo.valueMax - fmtInfo.valueMin;
896 	}
897 
898 	// Create textures.
899 	m_textures.reserve(2);
900 	for (int ndx = 0; ndx < 2; ndx++)
901 		m_textures.push_back(TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.depth)));
902 
903 	// Fill first gradient texture.
904 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
905 	{
906 		const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)*cScale + cBias;
907 		const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
908 
909 		if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
910 			tcu::fillWithComponentGradients(getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), gMin, gMax);
911 		else
912 			tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
913 
914 	}
915 
916 	// Fill second with grid texture.
917 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
918 	{
919 		const deUint32	step	= 0x00ffffff / numLevels;
920 		const deUint32	rgb		= step*levelNdx;
921 		const deUint32	colorA	= 0xff000000 | rgb;
922 		const deUint32	colorB	= 0xff000000 | ~rgb;
923 
924 		if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
925 			tcu::fillWithGrid(getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
926 		else
927 			tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
928 
929 	}
930 
931 	// Upload.
932 	for (vector<TestTexture3DSp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
933 	{
934 		m_renderer.add3DTexture(*i, testParameters.aspectMask);
935 	}
936 
937 	// Test cases
938 	m_cases.push_back(FilterCase(0,	tcu::Vec3(1.5f, 2.8f, 1.0f),	tcu::Vec3(-1.0f, -2.7f, -2.275f)));
939 	m_cases.push_back(FilterCase(0,	tcu::Vec3(-2.0f, -1.5f, -1.8f),	tcu::Vec3(-0.1f, 0.9f, -0.25f)));
940 	m_cases.push_back(FilterCase(1,	tcu::Vec3(0.2f, 0.175f, 0.3f),	tcu::Vec3(-2.0f, -3.7f, -1.825f)));
941 	m_cases.push_back(FilterCase(1,	tcu::Vec3(-0.8f, -2.3f, -2.5f),	tcu::Vec3(0.2f, -0.1f, 1.325f)));
942 }
943 
~Texture3DFilteringTestInstance(void)944 Texture3DFilteringTestInstance::~Texture3DFilteringTestInstance (void)
945 {
946 }
947 
iterate(void)948 tcu::TestStatus Texture3DFilteringTestInstance::iterate (void)
949 {
950 	tcu::TestLog&						log			= m_context.getTestContext().getLog();
951 
952 	const pipeline::TestTexture3D&	texture		= m_renderer.get3DTexture(m_cases[m_caseNdx].textureIndex);
953 	const tcu::TextureFormat		texFmt		= texture.getTextureFormat();
954 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFmt);
955 	const FilterCase&				curCase		= m_cases[m_caseNdx];
956 	ReferenceParams					refParams	(TEXTURETYPE_3D);
957 	tcu::Surface					rendered	(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
958 	tcu::Vec3						texCoord[4];
959 	const float* const				texCoordPtr	= (const float*)&texCoord[0];
960 
961 	// Params for reference computation.
962 	refParams.sampler		= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.wrapR, m_testParameters.minFilter, m_testParameters.magFilter);
963 	if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
964 	{
965 		refParams.sampler.depthStencilMode	= tcu::Sampler::MODE_STENCIL;
966 		refParams.samplerType				= SAMPLERTYPE_UINT;
967 	}
968 	else
969 		refParams.samplerType				= getSamplerType(texFmt);
970 	refParams.lodMode		= LODMODE_EXACT;
971 	refParams.colorBias		= fmtInfo.lookupBias;
972 	refParams.colorScale	= fmtInfo.lookupScale;
973 
974 	// Compute texture coordinates.
975 	log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset << TestLog::EndMessage;
976 
977 	{
978 		const float	lodX	= curCase.lod.x();
979 		const float	lodY	= curCase.lod.y();
980 		const float	lodZ	= curCase.lod.z();
981 		const float	oX		= curCase.offset.x();
982 		const float	oY		= curCase.offset.y();
983 		const float oZ		= curCase.offset.z();
984 		const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth())										/ float(m_textures[0]->getTexture().getWidth());
985 		const float	sY		= deFloatExp2(lodY) * float(m_renderer.getRenderHeight())										/ float(m_textures[0]->getTexture().getHeight());
986 		const float	sZ		= deFloatExp2(lodZ) * float(de::max(m_renderer.getRenderWidth(), m_renderer.getRenderHeight()))	/ float(m_textures[0]->getTexture().getDepth());
987 
988 		texCoord[0] = tcu::Vec3(oX,		oY,		oZ);
989 		texCoord[1] = tcu::Vec3(oX,		oY+sY,	oZ + sZ*0.5f);
990 		texCoord[2] = tcu::Vec3(oX+sX,	oY,		oZ + sZ*0.5f);
991 		texCoord[3] = tcu::Vec3(oX+sX,	oY+sY,	oZ + sZ);
992 	}
993 
994 	m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
995 
996 	{
997 		const bool				isNearestOnly	= m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
998 		const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
999 		const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1000 		const tcu::IVec4		colorBits		= max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
1001 		tcu::LodPrecision		lodPrecision;
1002 		tcu::LookupPrecision	lookupPrecision;
1003 
1004 		lodPrecision.derivateBits		= 18;
1005 		lodPrecision.lodBits			= 6;
1006 		lookupPrecision.colorThreshold	= tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
1007 		lookupPrecision.coordBits		= tcu::IVec3(20,20,20);
1008 		lookupPrecision.uvwBits			= tcu::IVec3(7,7,7);
1009 		lookupPrecision.colorMask		= getCompareMask(pixelFormat);
1010 
1011 		const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture3DView)texture.getTexture(),
1012 													   texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
1013 
1014 		if (!isHighQuality)
1015 		{
1016 			// Evaluate against lower precision requirements.
1017 			lodPrecision.lodBits	= 4;
1018 			lookupPrecision.uvwBits	= tcu::IVec3(4,4,4);
1019 
1020 			log << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
1021 
1022 			const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(), (tcu::Texture3DView)texture.getTexture(),
1023 												  texCoordPtr, refParams, lookupPrecision, lodPrecision, pixelFormat);
1024 
1025 			if (!isOk)
1026 			{
1027 				log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1028 				return tcu::TestStatus::fail("Image verification failed");
1029 			}
1030 		}
1031 	}
1032 
1033 	m_caseNdx += 1;
1034 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1035 }
1036 
verifierCanBeUsed(const VkFormat format,const Sampler::FilterMode minFilter,const Sampler::FilterMode magFilter)1037 bool verifierCanBeUsed(const VkFormat format, const Sampler::FilterMode minFilter, const Sampler::FilterMode magFilter)
1038 {
1039 	const tcu::TextureFormat				textureFormat		= mapVkFormat(format);
1040 	const tcu::TextureChannelClass			textureChannelClass	= tcu::getTextureChannelClass(textureFormat.type);
1041 
1042 	return !(!(textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1043 		textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1044 		textureChannelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) &&
1045 		(tcu::TexVerifierUtil::isLinearFilter(minFilter) || tcu::TexVerifierUtil::isLinearFilter(magFilter) ||
1046 		 tcu::TexVerifierUtil::isCubicFilter(minFilter)  || tcu::TexVerifierUtil::isCubicFilter(magFilter)));
1047 }
1048 
1049 } // anonymous
1050 
populateTextureFilteringTests(tcu::TestCaseGroup * textureFilteringTests)1051 void populateTextureFilteringTests (tcu::TestCaseGroup* textureFilteringTests)
1052 {
1053 	tcu::TestContext&	testCtx		= textureFilteringTests->getTestContext();
1054 
1055 	static const struct
1056 	{
1057 		const char* const			name;
1058 		const Sampler::WrapMode		mode;
1059 	} wrapModes[] =
1060 	{
1061 		{ "repeat",					Sampler::REPEAT_GL			},
1062 		{ "mirrored_repeat",		Sampler::MIRRORED_REPEAT_GL	},
1063 		{ "clamp_to_edge",			Sampler::CLAMP_TO_EDGE		},
1064 		{ "clamp_to_border",		Sampler::CLAMP_TO_BORDER	},
1065 		{ "mirror_clamp_to_edge",	Sampler::MIRRORED_ONCE		}
1066 	};
1067 
1068 	struct FilterModes
1069 	{
1070 		const char* const			name;
1071 		const Sampler::FilterMode	mode;
1072 	};
1073 
1074 	static const FilterModes minFilterModes[] =
1075 	{
1076 		{ "nearest",				Sampler::NEAREST					},
1077 		{ "linear",					Sampler::LINEAR						},
1078 		{ "nearest_mipmap_nearest",	Sampler::NEAREST_MIPMAP_NEAREST		},
1079 		{ "linear_mipmap_nearest",	Sampler::LINEAR_MIPMAP_NEAREST		},
1080 		{ "nearest_mipmap_linear",	Sampler::NEAREST_MIPMAP_LINEAR		},
1081 		{ "linear_mipmap_linear",	Sampler::LINEAR_MIPMAP_LINEAR		}
1082 	};
1083 
1084 	static const FilterModes magFilterModes[] =
1085 	{
1086 		{ "nearest",				Sampler::NEAREST },
1087 		{ "linear",					Sampler::LINEAR	 }
1088 	};
1089 
1090 	static const FilterModes minFilterModes2D[] =
1091 	{
1092 		{ "nearest",				Sampler::NEAREST					},
1093 		{ "linear",					Sampler::LINEAR						},
1094 		{ "cubic",					Sampler::CUBIC						},
1095 		{ "nearest_mipmap_nearest",	Sampler::NEAREST_MIPMAP_NEAREST		},
1096 		{ "linear_mipmap_nearest",	Sampler::LINEAR_MIPMAP_NEAREST		},
1097 		{ "nearest_mipmap_linear",	Sampler::NEAREST_MIPMAP_LINEAR		},
1098 		{ "linear_mipmap_linear",	Sampler::LINEAR_MIPMAP_LINEAR		},
1099 		{ "cubic_mipmap_nearest",	Sampler::CUBIC_MIPMAP_NEAREST		},
1100 		{ "cubic_mipmap_linear",	Sampler::CUBIC_MIPMAP_LINEAR		}
1101 	};
1102 
1103 	static const FilterModes magFilterModes2D[] =
1104 	{
1105 		{ "nearest",				Sampler::NEAREST },
1106 		{ "linear",					Sampler::LINEAR	 },
1107 		{ "cubic",					Sampler::CUBIC	 }
1108 	};
1109 
1110 	static const struct
1111 	{
1112 		const int	width;
1113 		const int	height;
1114 	} sizes2D[] =
1115 	{
1116 		{   4,	  8 },
1117 		{  32,	 64 },
1118 		{ 128,	128	},
1119 		{   3,	  7 },
1120 		{  31,	 55 },
1121 		{ 127,	 99 }
1122 	};
1123 
1124 	static const struct
1125 	{
1126 		const int	size;
1127 	} sizesCube[] =
1128 	{
1129 		{   8 },
1130 		{  64 },
1131 		{ 128 },
1132 		{   7 },
1133 		{  63 }
1134 	};
1135 
1136 	static const struct
1137 	{
1138 		const int	width;
1139 		const int	height;
1140 		const int	numLayers;
1141 	} sizes2DArray[] =
1142 	{
1143 		{   4,   8,   8 },
1144 		{  32,  64,  16 },
1145 		{ 128,  32,  64 },
1146 		{   3,   7,   5 },
1147 		{  63,  63,  63 }
1148 	};
1149 
1150 	static const struct
1151 	{
1152 		const int	width;
1153 		const int	height;
1154 		const int	depth;
1155 	} sizes3D[] =
1156 	{
1157 		{   4,   8,   8 },
1158 		{  32,  64,  16 },
1159 		{ 128,  32,  64 },
1160 		{   3,   7,   5 },
1161 		{  63,  63,  63 }
1162 	};
1163 
1164 	static const struct
1165 	{
1166 		const char* const			name;
1167 		const VkFormat				format;
1168 		const VkImageAspectFlags	aspectMask;
1169 		const Program				program2D;
1170 		const Program				programCube;
1171 		const Program				program2DArray;
1172 		const Program				program3D;
1173 	} filterableFormatsByType[] =
1174 	{
1175 		{ "r16g16b16a16_sfloat",			VK_FORMAT_R16G16B16A16_SFLOAT,					VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1176 		{ "b10g11r11_ufloat",				VK_FORMAT_B10G11R11_UFLOAT_PACK32,				VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1177 		{ "e5b9g9r9_ufloat",				VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,				VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1178 		{ "r8g8b8a8_unorm",					VK_FORMAT_R8G8B8A8_UNORM,						VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1179 		{ "r8g8b8a8_snorm",					VK_FORMAT_R8G8B8A8_SNORM,						VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1180 		{ "r5g6b5_unorm",					VK_FORMAT_R5G6B5_UNORM_PACK16,					VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1181 		{ "r10x6g10x6b10x6a10x6_unorm",		VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,	VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1182 		{ "r4g4b4a4_unorm",					VK_FORMAT_R4G4B4A4_UNORM_PACK16,				VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1183 		{ "a4r4g4b4_unorm",					VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,			VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1184 		{ "a4b4g4r4_unorm",					VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,			VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1185 		{ "r5g5b5a1_unorm",					VK_FORMAT_R5G5B5A1_UNORM_PACK16,				VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1186 		{ "a8b8g8r8_srgb",					VK_FORMAT_A8B8G8R8_SRGB_PACK32,					VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1187 		{ "a1r5g5b5_unorm",					VK_FORMAT_A1R5G5B5_UNORM_PACK16,				VK_IMAGE_ASPECT_COLOR_BIT,		PROGRAM_2D_FLOAT,	PROGRAM_CUBE_FLOAT,	PROGRAM_2D_ARRAY_FLOAT,	PROGRAM_3D_FLOAT	},
1188 		{ "s8_uint",						VK_FORMAT_S8_UINT,								VK_IMAGE_ASPECT_STENCIL_BIT,	PROGRAM_2D_UINT,	PROGRAM_CUBE_UINT,	PROGRAM_2D_ARRAY_UINT,	PROGRAM_3D_UINT		},
1189 		{ "d24_unorm_s8_uint_stencil",		VK_FORMAT_D24_UNORM_S8_UINT,					VK_IMAGE_ASPECT_STENCIL_BIT,	PROGRAM_2D_UINT,	PROGRAM_CUBE_UINT,	PROGRAM_2D_ARRAY_UINT,	PROGRAM_3D_UINT		},
1190 		{ "d32_sfloat_s8_uint_stencil",		VK_FORMAT_D32_SFLOAT_S8_UINT,					VK_IMAGE_ASPECT_STENCIL_BIT,	PROGRAM_2D_UINT,	PROGRAM_CUBE_UINT,	PROGRAM_2D_ARRAY_UINT,	PROGRAM_3D_UINT		}
1191 	};
1192 
1193 	// 2D texture filtering.
1194 	{
1195 		de::MovePtr<tcu::TestCaseGroup>	group2D				(new tcu::TestCaseGroup(testCtx, "2d", "2D Texture Filtering"));
1196 
1197 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1198 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1199 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup	(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1200 
1201 		// Formats.
1202 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1203 		{
1204 			const string					filterGroupName	= filterableFormatsByType[fmtNdx].name;
1205 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1206 
1207 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1208 			{
1209 				const Sampler::FilterMode	minFilter		= minFilterModes2D[filterNdx].mode;
1210 				const bool					isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1211 				const string				name			= minFilterModes2D[filterNdx].name;
1212 				Texture2DTestCaseParameters	testParameters;
1213 
1214 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1215 				testParameters.minFilter	= minFilter;
1216 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1217 				testParameters.mipmaps		= true;
1218 
1219 				testParameters.wrapS		= Sampler::REPEAT_GL;
1220 				testParameters.wrapT		= Sampler::REPEAT_GL;
1221 				testParameters.width		= 64;
1222 				testParameters.height		= 64;
1223 
1224 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1225 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1226 
1227 				// Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1228 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1229 				{
1230 					filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1231 				}
1232 			}
1233 			formatsGroup->addChild(filterGroup.release());
1234 		}
1235 
1236 		// Sizes.
1237 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1238 		{
1239 			const string					filterGroupName = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1240 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1241 
1242 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1243 			{
1244 				const Sampler::FilterMode	minFilter		= minFilterModes2D[filterNdx].mode;
1245 				const bool					isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1246 				const string				name			= minFilterModes2D[filterNdx].name;
1247 				Texture2DTestCaseParameters	testParameters;
1248 
1249 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1250 				testParameters.minFilter	= minFilter;
1251 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1252 				testParameters.mipmaps		= true;
1253 
1254 				testParameters.wrapS		= Sampler::REPEAT_GL;
1255 				testParameters.wrapT		= Sampler::REPEAT_GL;
1256 				testParameters.width		= sizes2D[sizeNdx].width;
1257 				testParameters.height		= sizes2D[sizeNdx].height;
1258 
1259 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1260 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1261 
1262 				filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1263 			}
1264 			sizesGroup->addChild(filterGroup.release());
1265 		}
1266 
1267 		// Wrap modes.
1268 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); minFilterNdx++)
1269 		{
1270 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes2D[minFilterNdx].name, ""));
1271 
1272 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); magFilterNdx++)
1273 			{
1274 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes2D[magFilterNdx].name, ""));
1275 
1276 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1277 				{
1278 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1279 
1280 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1281 					{
1282 						const string	name		= wrapModes[wrapTNdx].name;
1283 						Texture2DTestCaseParameters	testParameters;
1284 
1285 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1286 						testParameters.minFilter	= minFilterModes2D[minFilterNdx].mode;
1287 						testParameters.magFilter	= magFilterModes2D[magFilterNdx].mode;
1288 						testParameters.mipmaps		= true;
1289 
1290 						testParameters.wrapS		= wrapModes[wrapSNdx].mode;
1291 						testParameters.wrapT		= wrapModes[wrapTNdx].mode;
1292 						testParameters.width		= 63;
1293 						testParameters.height		= 57;
1294 
1295 						testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1296 						testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1297 
1298 						wrapSGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1299 					}
1300 					magFilterGroup->addChild(wrapSGroup.release());
1301 				}
1302 				minFilterGroup->addChild(magFilterGroup.release());
1303 			}
1304 			combinationsGroup->addChild(minFilterGroup.release());
1305 		}
1306 
1307 		group2D->addChild(formatsGroup.release());
1308 		group2D->addChild(sizesGroup.release());
1309 		group2D->addChild(combinationsGroup.release());
1310 
1311 		textureFilteringTests->addChild(group2D.release());
1312 	}
1313 
1314 	// Unnormalized texture filtering.
1315 	{
1316 		de::MovePtr<tcu::TestCaseGroup>	groupUnnormal		(new tcu::TestCaseGroup(testCtx, "unnormal", "Unnormalized Texture Filtering"));
1317 
1318 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1319 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1320 
1321 		// Formats.
1322 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1323 		{
1324 			const string					filterGroupName	= filterableFormatsByType[fmtNdx].name;
1325 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1326 
1327 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1328 			{
1329 				const Sampler::FilterMode	magFilter		= magFilterModes2D[filterNdx].mode;
1330 				const string				name			= magFilterModes2D[filterNdx].name;
1331 				Texture2DTestCaseParameters	testParameters;
1332 
1333 				testParameters.unnormal		= true;
1334 
1335 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1336 				testParameters.minFilter	= magFilter;
1337 				testParameters.magFilter	= magFilter;
1338 				testParameters.mipmaps		= false;
1339 
1340 				testParameters.wrapS		= ((fmtNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1341 				testParameters.wrapT		= ((fmtNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1342 				testParameters.width		= 64;
1343 				testParameters.height		= 64;
1344 
1345 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1346 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1347 
1348 				// Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1349 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1350 				{
1351 					filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1352 				}
1353 			}
1354 			formatsGroup->addChild(filterGroup.release());
1355 		}
1356 
1357 		// Sizes.
1358 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1359 		{
1360 			const string					filterGroupName = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1361 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1362 
1363 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1364 			{
1365 				const Sampler::FilterMode	magFilter		= magFilterModes2D[filterNdx].mode;
1366 				const string				name			= magFilterModes2D[filterNdx].name;
1367 				Texture2DTestCaseParameters	testParameters;
1368 
1369 				testParameters.unnormal		= true;
1370 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1371 				testParameters.minFilter	= magFilter;
1372 				testParameters.magFilter	= magFilter;
1373 				testParameters.mipmaps		= false;
1374 
1375 				testParameters.wrapS		= ((sizeNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1376 				testParameters.wrapT		= ((sizeNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1377 				testParameters.width		= sizes2D[sizeNdx].width;
1378 				testParameters.height		= sizes2D[sizeNdx].height;
1379 
1380 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1381 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1382 
1383 				filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1384 			}
1385 			sizesGroup->addChild(filterGroup.release());
1386 		}
1387 
1388 		groupUnnormal->addChild(formatsGroup.release());
1389 		groupUnnormal->addChild(sizesGroup.release());
1390 
1391 		textureFilteringTests->addChild(groupUnnormal.release());
1392 	}
1393 
1394 	// Cube map texture filtering.
1395 	{
1396 		de::MovePtr<tcu::TestCaseGroup>	groupCube				(new tcu::TestCaseGroup(testCtx, "cube", "Cube Map Texture Filtering"));
1397 
1398 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup			(new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1399 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup				(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1400 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup		(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1401 		de::MovePtr<tcu::TestCaseGroup>	onlyFaceInteriorGroup	(new tcu::TestCaseGroup(testCtx, "no_edges_visible", "Don't sample anywhere near a face's edges"));
1402 
1403 		// Formats.
1404 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1405 		{
1406 			const string					filterGroupName = filterableFormatsByType[fmtNdx].name;
1407 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1408 
1409 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1410 			{
1411 				const Sampler::FilterMode				minFilter	= minFilterModes[filterNdx].mode;
1412 				const bool								isMipmap	= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1413 				const string							name		= minFilterModes[filterNdx].name;
1414 				TextureCubeFilteringTestCaseParameters	testParameters;
1415 
1416 				testParameters.format					= filterableFormatsByType[fmtNdx].format;
1417 				testParameters.minFilter				= minFilter;
1418 				testParameters.magFilter				= isMipmap ? Sampler::LINEAR : minFilter;
1419 
1420 				testParameters.wrapS					= Sampler::REPEAT_GL;
1421 				testParameters.wrapT					= Sampler::REPEAT_GL;
1422 				testParameters.onlySampleFaceInterior	= false;
1423 				testParameters.size						= 64;
1424 
1425 				testParameters.aspectMask				= filterableFormatsByType[fmtNdx].aspectMask;
1426 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].programCube);
1427 
1428 				// Some tests have to be skipped due to the restrictions of the verifiers.
1429 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1430 				{
1431 					filterGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1432 				}
1433 			}
1434 			formatsGroup->addChild(filterGroup.release());
1435 		}
1436 
1437 		// Sizes.
1438 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
1439 		{
1440 			const string					filterGroupName = de::toString(sizesCube[sizeNdx].size) + "x" + de::toString(sizesCube[sizeNdx].size);
1441 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1442 
1443 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1444 			{
1445 				const Sampler::FilterMode				minFilter		= minFilterModes[filterNdx].mode;
1446 				const bool								isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1447 				const string							name			= minFilterModes[filterNdx].name;
1448 				TextureCubeFilteringTestCaseParameters	testParameters;
1449 
1450 				testParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
1451 				testParameters.minFilter				= minFilter;
1452 				testParameters.magFilter				= isMipmap ? Sampler::LINEAR : minFilter;
1453 				testParameters.wrapS					= Sampler::REPEAT_GL;
1454 				testParameters.wrapT					= Sampler::REPEAT_GL;
1455 				testParameters.onlySampleFaceInterior	= false;
1456 				testParameters.size						= sizesCube[sizeNdx].size;
1457 
1458 				testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
1459 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1460 
1461 				filterGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1462 
1463 			}
1464 			sizesGroup->addChild(filterGroup.release());
1465 		}
1466 
1467 		// Filter/wrap mode combinations.
1468 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1469 		{
1470 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1471 
1472 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1473 			{
1474 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1475 
1476 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1477 				{
1478 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1479 
1480 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1481 					{
1482 						const string							name			= wrapModes[wrapTNdx].name;
1483 						TextureCubeFilteringTestCaseParameters	testParameters;
1484 
1485 						testParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
1486 						testParameters.minFilter				= minFilterModes[minFilterNdx].mode;
1487 						testParameters.magFilter				= magFilterModes[magFilterNdx].mode;
1488 						testParameters.wrapS					= wrapModes[wrapSNdx].mode;
1489 						testParameters.wrapT					= wrapModes[wrapTNdx].mode;
1490 						testParameters.onlySampleFaceInterior	= false;
1491 						testParameters.size						= 63;
1492 
1493 						testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
1494 						testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1495 
1496 						wrapSGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1497 					}
1498 					magFilterGroup->addChild(wrapSGroup.release());
1499 				}
1500 				minFilterGroup->addChild(magFilterGroup.release());
1501 			}
1502 			combinationsGroup->addChild(minFilterGroup.release());
1503 		}
1504 
1505 		// Cases with no visible cube edges.
1506 		for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
1507 		{
1508 			const bool								isLinear		= isLinearI != 0;
1509 			const string							name			= isLinear ? "linear" : "nearest";
1510 			TextureCubeFilteringTestCaseParameters	testParameters;
1511 
1512 			testParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
1513 			testParameters.minFilter				= isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1514 			testParameters.magFilter				= isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1515 			testParameters.wrapS					= Sampler::REPEAT_GL;
1516 			testParameters.wrapT					= Sampler::REPEAT_GL;
1517 			testParameters.onlySampleFaceInterior	= true;
1518 			testParameters.size						= 63;
1519 
1520 			testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
1521 			testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1522 
1523 			onlyFaceInteriorGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1524 		}
1525 
1526 		groupCube->addChild(formatsGroup.release());
1527 		groupCube->addChild(sizesGroup.release());
1528 		groupCube->addChild(combinationsGroup.release());
1529 		groupCube->addChild(onlyFaceInteriorGroup.release());
1530 
1531 		textureFilteringTests->addChild(groupCube.release());
1532 	}
1533 
1534 	// 2D array texture filtering.
1535 	{
1536 		de::MovePtr<tcu::TestCaseGroup>	group2DArray		(new tcu::TestCaseGroup(testCtx, "2d_array", "2D Array Texture Filtering"));
1537 
1538 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "2D Array Texture Formats"));
1539 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1540 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup	(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1541 
1542 		// Formats.
1543 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1544 		{
1545 			const string					filterGroupName = filterableFormatsByType[fmtNdx].name;
1546 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1547 
1548 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1549 			{
1550 				const Sampler::FilterMode			minFilter		= minFilterModes[filterNdx].mode;
1551 				const char* const					filterName		= minFilterModes[filterNdx].name;
1552 				const bool							isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1553 				const char* const					formatName		= filterableFormatsByType[fmtNdx].name;
1554 				const string						name			= string(formatName) + "_" + filterName;
1555 				Texture2DArrayTestCaseParameters	testParameters;
1556 
1557 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1558 				testParameters.minFilter	= minFilter;
1559 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1560 
1561 				testParameters.wrapS		= Sampler::REPEAT_GL;
1562 				testParameters.wrapT		= Sampler::REPEAT_GL;
1563 				testParameters.width		= 128;
1564 				testParameters.height		= 128;
1565 				testParameters.numLayers	= 8;
1566 
1567 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1568 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2DArray);
1569 
1570 				// Some tests have to be skipped due to the restrictions of the verifiers.
1571 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1572 				{
1573 					filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1574 				}
1575 			}
1576 			formatsGroup->addChild(filterGroup.release());
1577 		}
1578 
1579 		// Sizes.
1580 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2DArray); sizeNdx++)
1581 		{
1582 			const string					filterGroupName = de::toString(sizes2DArray[sizeNdx].width) + "x" + de::toString(sizes2DArray[sizeNdx].height) + "x" + de::toString(sizes2DArray[sizeNdx].numLayers);
1583 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1584 
1585 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1586 			{
1587 				const Sampler::FilterMode			minFilter		= minFilterModes[filterNdx].mode;
1588 				const char* const					filterName		= minFilterModes[filterNdx].name;
1589 				const bool							isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1590 				const string						name			= filterName;
1591 				Texture2DArrayTestCaseParameters	testParameters;
1592 
1593 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1594 				testParameters.minFilter	= minFilter;
1595 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1596 				testParameters.wrapS		= Sampler::REPEAT_GL;
1597 				testParameters.wrapT		= Sampler::REPEAT_GL;
1598 				testParameters.width		= sizes2DArray[sizeNdx].width;
1599 				testParameters.height		= sizes2DArray[sizeNdx].height;
1600 				testParameters.numLayers	= sizes2DArray[sizeNdx].numLayers;
1601 
1602 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1603 				testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1604 
1605 				filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1606 			}
1607 			sizesGroup->addChild(filterGroup.release());
1608 		}
1609 
1610 		// Wrap modes.
1611 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1612 		{
1613 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1614 
1615 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1616 			{
1617 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1618 
1619 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1620 				{
1621 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1622 
1623 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1624 					{
1625 						const string						name			= wrapModes[wrapTNdx].name;
1626 						Texture2DArrayTestCaseParameters	testParameters;
1627 
1628 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1629 						testParameters.minFilter	= minFilterModes[minFilterNdx].mode;
1630 						testParameters.magFilter	= magFilterModes[magFilterNdx].mode;
1631 						testParameters.wrapS		= wrapModes[wrapSNdx].mode;
1632 						testParameters.wrapT		= wrapModes[wrapTNdx].mode;
1633 						testParameters.width		= 123;
1634 						testParameters.height		= 107;
1635 						testParameters.numLayers	= 7;
1636 
1637 						testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1638 						testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1639 
1640 						wrapSGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1641 					}
1642 					magFilterGroup->addChild(wrapSGroup.release());
1643 				}
1644 				minFilterGroup->addChild(magFilterGroup.release());
1645 			}
1646 			combinationsGroup->addChild(minFilterGroup.release());
1647 		}
1648 
1649 		group2DArray->addChild(formatsGroup.release());
1650 		group2DArray->addChild(sizesGroup.release());
1651 		group2DArray->addChild(combinationsGroup.release());
1652 
1653 		textureFilteringTests->addChild(group2DArray.release());
1654 	}
1655 
1656 	// 3D texture filtering.
1657 	{
1658 		de::MovePtr<tcu::TestCaseGroup>	group3D				(new tcu::TestCaseGroup(testCtx, "3d", "3D Texture Filtering"));
1659 
1660 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "3D Texture Formats"));
1661 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1662 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup	(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1663 
1664 		// Formats.
1665 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1666 		{
1667 			const string					filterGroupName = filterableFormatsByType[fmtNdx].name;
1668 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1669 
1670 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1671 			{
1672 				const Sampler::FilterMode	minFilter		= minFilterModes[filterNdx].mode;
1673 				const char* const			filterName		= minFilterModes[filterNdx].name;
1674 				const bool					isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1675 				const char* const			formatName		= filterableFormatsByType[fmtNdx].name;
1676 				const string				name			= string(formatName) + "_" + filterName;
1677 				Texture3DTestCaseParameters	testParameters;
1678 
1679 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1680 				testParameters.minFilter	= minFilter;
1681 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1682 
1683 				testParameters.wrapS		= Sampler::REPEAT_GL;
1684 				testParameters.wrapT		= Sampler::REPEAT_GL;
1685 				testParameters.wrapR		= Sampler::REPEAT_GL;
1686 				testParameters.width		= 64;
1687 				testParameters.height		= 64;
1688 				testParameters.depth		= 64;
1689 
1690 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1691 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program3D);
1692 
1693 				// Some tests have to be skipped due to the restrictions of the verifiers.
1694 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1695 				{
1696 					filterGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1697 				}
1698 			}
1699 			formatsGroup->addChild(filterGroup.release());
1700 		}
1701 
1702 		// Sizes.
1703 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes3D); sizeNdx++)
1704 		{
1705 			const string					filterGroupName = de::toString(sizes3D[sizeNdx].width) + "x" + de::toString(sizes3D[sizeNdx].height) + "x" + de::toString(sizes3D[sizeNdx].depth);
1706 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1707 
1708 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1709 			{
1710 				const Sampler::FilterMode		minFilter		= minFilterModes[filterNdx].mode;
1711 				const char* const				filterName		= minFilterModes[filterNdx].name;
1712 				const bool						isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1713 				const string					name			= filterName;
1714 				Texture3DTestCaseParameters		testParameters;
1715 
1716 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1717 				testParameters.minFilter	= minFilter;
1718 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1719 				testParameters.wrapS		= Sampler::REPEAT_GL;
1720 				testParameters.wrapT		= Sampler::REPEAT_GL;
1721 				testParameters.wrapR		= Sampler::REPEAT_GL;
1722 				testParameters.width		= sizes3D[sizeNdx].width;
1723 				testParameters.height		= sizes3D[sizeNdx].height;
1724 				testParameters.depth		= sizes3D[sizeNdx].depth;
1725 
1726 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1727 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1728 
1729 				filterGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1730 			}
1731 			sizesGroup->addChild(filterGroup.release());
1732 		}
1733 
1734 		// Wrap modes.
1735 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1736 		{
1737 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1738 
1739 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1740 			{
1741 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1742 
1743 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1744 				{
1745 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1746 
1747 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1748 					{
1749 						de::MovePtr<tcu::TestCaseGroup>	wrapTGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapTNdx].name, ""));
1750 
1751 						for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
1752 						{
1753 							const string				name			= wrapModes[wrapRNdx].name;
1754 							Texture3DTestCaseParameters	testParameters;
1755 
1756 							testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1757 							testParameters.minFilter	= minFilterModes[minFilterNdx].mode;
1758 							testParameters.magFilter	= magFilterModes[magFilterNdx].mode;
1759 							testParameters.wrapS		= wrapModes[wrapSNdx].mode;
1760 							testParameters.wrapT		= wrapModes[wrapTNdx].mode;
1761 							testParameters.wrapR		= wrapModes[wrapRNdx].mode;
1762 							testParameters.width		= 63;
1763 							testParameters.height		= 57;
1764 							testParameters.depth		= 67;
1765 
1766 							testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1767 							testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1768 
1769 							wrapTGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1770 						}
1771 						wrapSGroup->addChild(wrapTGroup.release());
1772 					}
1773 					magFilterGroup->addChild(wrapSGroup.release());
1774 				}
1775 				minFilterGroup->addChild(magFilterGroup.release());
1776 			}
1777 			combinationsGroup->addChild(minFilterGroup.release());
1778 		}
1779 
1780 		group3D->addChild(formatsGroup.release());
1781 		group3D->addChild(sizesGroup.release());
1782 		group3D->addChild(combinationsGroup.release());
1783 
1784 		textureFilteringTests->addChild(group3D.release());
1785 	}
1786 }
1787 
createTextureFilteringTests(tcu::TestContext & testCtx)1788 tcu::TestCaseGroup*	createTextureFilteringTests	(tcu::TestContext& testCtx)
1789 {
1790 	return createTestGroup(testCtx, "filtering", "Texture filtering tests.", populateTextureFilteringTests);
1791 }
1792 
1793 } // texture
1794 } // vkt
1795