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