• 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::__anon9a19a5410111::Texture2DFilteringTestInstance::FilterCase205 		FilterCase (void)
206 			: textureIndex(-1)
207 		{
208 		}
209 
FilterCasevkt::texture::__anon9a19a5410111::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::__anon9a19a5410111::TextureCubeFilteringTestInstance::FilterCase422 		FilterCase (void)
423 			: textureIndex(-1)
424 		{
425 		}
426 
FilterCasevkt::texture::__anon9a19a5410111::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::__anon9a19a5410111::Texture2DArrayFilteringTestInstance::FilterCase669 		FilterCase (void)
670 			: textureIndex(-1)
671 		{
672 		}
673 
FilterCasevkt::texture::__anon9a19a5410111::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::__anon9a19a5410111::Texture3DFilteringTestInstance::FilterCase893 		FilterCase (void)
894 			: textureIndex(-1)
895 		{
896 		}
897 
FilterCasevkt::texture::__anon9a19a5410111::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 		de::MovePtr<tcu::TestCaseGroup>	group2D				(new tcu::TestCaseGroup(testCtx, "2d", "2D Texture Filtering"));
1239 
1240 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1241 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1242 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup	(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1243 
1244 		// Formats.
1245 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1246 		{
1247 			const string					filterGroupName	= filterableFormatsByType[fmtNdx].name;
1248 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1249 
1250 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1251 			{
1252 				const Sampler::FilterMode	minFilter		= minFilterModes2D[filterNdx].mode;
1253 				const bool					isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1254 				const string				name			= minFilterModes2D[filterNdx].name;
1255 				Texture2DTestCaseParameters	testParameters;
1256 
1257 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1258 				testParameters.minFilter	= minFilter;
1259 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1260 				testParameters.mipmaps		= true;
1261 
1262 				testParameters.wrapS		= Sampler::REPEAT_GL;
1263 				testParameters.wrapT		= Sampler::REPEAT_GL;
1264 				testParameters.width		= 64;
1265 				testParameters.height		= 64;
1266 
1267 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1268 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1269 
1270 				// Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1271 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1272 				{
1273 					filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1274 				}
1275 			}
1276 			formatsGroup->addChild(filterGroup.release());
1277 		}
1278 
1279 		// Sizes.
1280 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1281 		{
1282 			const string					filterGroupName = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1283 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1284 
1285 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1286 			{
1287 				const Sampler::FilterMode	minFilter		= minFilterModes2D[filterNdx].mode;
1288 				const bool					isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1289 				const string				name			= minFilterModes2D[filterNdx].name;
1290 				Texture2DTestCaseParameters	testParameters;
1291 
1292 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1293 				testParameters.minFilter	= minFilter;
1294 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1295 				testParameters.mipmaps		= true;
1296 
1297 				testParameters.wrapS		= Sampler::REPEAT_GL;
1298 				testParameters.wrapT		= Sampler::REPEAT_GL;
1299 				testParameters.width		= sizes2D[sizeNdx].width;
1300 				testParameters.height		= sizes2D[sizeNdx].height;
1301 
1302 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1303 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1304 
1305 				filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1306 			}
1307 			sizesGroup->addChild(filterGroup.release());
1308 		}
1309 
1310 		// Wrap modes.
1311 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); minFilterNdx++)
1312 		{
1313 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes2D[minFilterNdx].name, ""));
1314 
1315 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); magFilterNdx++)
1316 			{
1317 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes2D[magFilterNdx].name, ""));
1318 
1319 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1320 				{
1321 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1322 
1323 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1324 					{
1325 						const string	name		= wrapModes[wrapTNdx].name;
1326 						Texture2DTestCaseParameters	testParameters;
1327 
1328 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1329 						testParameters.minFilter	= minFilterModes2D[minFilterNdx].mode;
1330 						testParameters.magFilter	= magFilterModes2D[magFilterNdx].mode;
1331 						testParameters.mipmaps		= true;
1332 
1333 						testParameters.wrapS		= wrapModes[wrapSNdx].mode;
1334 						testParameters.wrapT		= wrapModes[wrapTNdx].mode;
1335 						testParameters.width		= 63;
1336 						testParameters.height		= 57;
1337 
1338 						testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1339 						testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1340 
1341 						wrapSGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1342 					}
1343 					magFilterGroup->addChild(wrapSGroup.release());
1344 				}
1345 				minFilterGroup->addChild(magFilterGroup.release());
1346 			}
1347 			combinationsGroup->addChild(minFilterGroup.release());
1348 		}
1349 
1350 		group2D->addChild(formatsGroup.release());
1351 		group2D->addChild(sizesGroup.release());
1352 		group2D->addChild(combinationsGroup.release());
1353 
1354 		textureFilteringTests->addChild(group2D.release());
1355 	}
1356 
1357 	// Unnormalized texture filtering.
1358 	{
1359 		de::MovePtr<tcu::TestCaseGroup>	groupUnnormal		(new tcu::TestCaseGroup(testCtx, "unnormal", "Unnormalized Texture Filtering"));
1360 
1361 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1362 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1363 
1364 		// Formats.
1365 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1366 		{
1367 			const string					filterGroupName	= filterableFormatsByType[fmtNdx].name;
1368 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1369 
1370 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1371 			{
1372 				const Sampler::FilterMode	magFilter		= magFilterModes2D[filterNdx].mode;
1373 				const string				name			= magFilterModes2D[filterNdx].name;
1374 				Texture2DTestCaseParameters	testParameters;
1375 
1376 				testParameters.unnormal		= true;
1377 
1378 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1379 				testParameters.minFilter	= magFilter;
1380 				testParameters.magFilter	= magFilter;
1381 				testParameters.mipmaps		= false;
1382 
1383 				testParameters.wrapS		= ((fmtNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1384 				testParameters.wrapT		= ((fmtNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1385 				testParameters.width		= 64;
1386 				testParameters.height		= 64;
1387 
1388 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1389 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1390 
1391 				// Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1392 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1393 				{
1394 					filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1395 				}
1396 			}
1397 			formatsGroup->addChild(filterGroup.release());
1398 		}
1399 
1400 		// Sizes.
1401 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1402 		{
1403 			const string					filterGroupName = de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1404 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1405 
1406 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1407 			{
1408 				const Sampler::FilterMode	magFilter		= magFilterModes2D[filterNdx].mode;
1409 				const string				name			= magFilterModes2D[filterNdx].name;
1410 				Texture2DTestCaseParameters	testParameters;
1411 
1412 				testParameters.unnormal		= true;
1413 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1414 				testParameters.minFilter	= magFilter;
1415 				testParameters.magFilter	= magFilter;
1416 				testParameters.mipmaps		= false;
1417 
1418 				testParameters.wrapS		= ((sizeNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1419 				testParameters.wrapT		= ((sizeNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1420 				testParameters.width		= sizes2D[sizeNdx].width;
1421 				testParameters.height		= sizes2D[sizeNdx].height;
1422 
1423 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1424 				testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1425 
1426 				filterGroup->addChild(new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1427 			}
1428 			sizesGroup->addChild(filterGroup.release());
1429 		}
1430 
1431 		groupUnnormal->addChild(formatsGroup.release());
1432 		groupUnnormal->addChild(sizesGroup.release());
1433 
1434 		textureFilteringTests->addChild(groupUnnormal.release());
1435 	}
1436 
1437 	// Cube map texture filtering.
1438 	{
1439 		de::MovePtr<tcu::TestCaseGroup>	groupCube				(new tcu::TestCaseGroup(testCtx, "cube", "Cube Map Texture Filtering"));
1440 
1441 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup			(new tcu::TestCaseGroup(testCtx, "formats", "2D Texture Formats"));
1442 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup				(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1443 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup		(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1444 		de::MovePtr<tcu::TestCaseGroup>	onlyFaceInteriorGroup	(new tcu::TestCaseGroup(testCtx, "no_edges_visible", "Don't sample anywhere near a face's edges"));
1445 
1446 		// Formats.
1447 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1448 		{
1449 			const string					filterGroupName = filterableFormatsByType[fmtNdx].name;
1450 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1451 
1452 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1453 			{
1454 				const Sampler::FilterMode				minFilter	= minFilterModes[filterNdx].mode;
1455 				const bool								isMipmap	= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1456 				const string							name		= minFilterModes[filterNdx].name;
1457 				TextureCubeFilteringTestCaseParameters	testParameters;
1458 
1459 				testParameters.format					= filterableFormatsByType[fmtNdx].format;
1460 				testParameters.minFilter				= minFilter;
1461 				testParameters.magFilter				= isMipmap ? Sampler::LINEAR : minFilter;
1462 
1463 				testParameters.wrapS					= Sampler::REPEAT_GL;
1464 				testParameters.wrapT					= Sampler::REPEAT_GL;
1465 				testParameters.onlySampleFaceInterior	= false;
1466 				testParameters.size						= 64;
1467 
1468 				testParameters.aspectMask				= filterableFormatsByType[fmtNdx].aspectMask;
1469 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].programCube);
1470 
1471 				// Some tests have to be skipped due to the restrictions of the verifiers.
1472 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1473 				{
1474 					filterGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1475 				}
1476 			}
1477 			formatsGroup->addChild(filterGroup.release());
1478 		}
1479 
1480 		// Sizes.
1481 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
1482 		{
1483 			const string					filterGroupName = de::toString(sizesCube[sizeNdx].size) + "x" + de::toString(sizesCube[sizeNdx].size);
1484 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1485 
1486 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1487 			{
1488 				const Sampler::FilterMode				minFilter		= minFilterModes[filterNdx].mode;
1489 				const bool								isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1490 				const string							name			= minFilterModes[filterNdx].name;
1491 				TextureCubeFilteringTestCaseParameters	testParameters;
1492 
1493 				testParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
1494 				testParameters.minFilter				= minFilter;
1495 				testParameters.magFilter				= isMipmap ? Sampler::LINEAR : minFilter;
1496 				testParameters.wrapS					= Sampler::REPEAT_GL;
1497 				testParameters.wrapT					= Sampler::REPEAT_GL;
1498 				testParameters.onlySampleFaceInterior	= false;
1499 				testParameters.size						= sizesCube[sizeNdx].size;
1500 
1501 				testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
1502 				testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1503 
1504 				filterGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1505 
1506 			}
1507 			sizesGroup->addChild(filterGroup.release());
1508 		}
1509 
1510 		// Filter/wrap mode combinations.
1511 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1512 		{
1513 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1514 
1515 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1516 			{
1517 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1518 
1519 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1520 				{
1521 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1522 
1523 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1524 					{
1525 						const string							name			= wrapModes[wrapTNdx].name;
1526 						TextureCubeFilteringTestCaseParameters	testParameters;
1527 
1528 						testParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
1529 						testParameters.minFilter				= minFilterModes[minFilterNdx].mode;
1530 						testParameters.magFilter				= magFilterModes[magFilterNdx].mode;
1531 						testParameters.wrapS					= wrapModes[wrapSNdx].mode;
1532 						testParameters.wrapT					= wrapModes[wrapTNdx].mode;
1533 						testParameters.onlySampleFaceInterior	= false;
1534 						testParameters.size						= 63;
1535 
1536 						testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
1537 						testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1538 
1539 						wrapSGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1540 					}
1541 					magFilterGroup->addChild(wrapSGroup.release());
1542 				}
1543 				minFilterGroup->addChild(magFilterGroup.release());
1544 			}
1545 			combinationsGroup->addChild(minFilterGroup.release());
1546 		}
1547 
1548 		// Cases with no visible cube edges.
1549 		for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
1550 		{
1551 			const bool								isLinear		= isLinearI != 0;
1552 			const string							name			= isLinear ? "linear" : "nearest";
1553 			TextureCubeFilteringTestCaseParameters	testParameters;
1554 
1555 			testParameters.format					= VK_FORMAT_R8G8B8A8_UNORM;
1556 			testParameters.minFilter				= isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1557 			testParameters.magFilter				= isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1558 			testParameters.wrapS					= Sampler::REPEAT_GL;
1559 			testParameters.wrapT					= Sampler::REPEAT_GL;
1560 			testParameters.onlySampleFaceInterior	= true;
1561 			testParameters.size						= 63;
1562 
1563 			testParameters.aspectMask				= VK_IMAGE_ASPECT_COLOR_BIT;
1564 			testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1565 
1566 			onlyFaceInteriorGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1567 		}
1568 
1569 		groupCube->addChild(formatsGroup.release());
1570 		groupCube->addChild(sizesGroup.release());
1571 		groupCube->addChild(combinationsGroup.release());
1572 		groupCube->addChild(onlyFaceInteriorGroup.release());
1573 
1574 		textureFilteringTests->addChild(groupCube.release());
1575 	}
1576 
1577 	// 2D array texture filtering.
1578 	{
1579 		de::MovePtr<tcu::TestCaseGroup>	group2DArray		(new tcu::TestCaseGroup(testCtx, "2d_array", "2D Array Texture Filtering"));
1580 
1581 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "2D Array Texture Formats"));
1582 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1583 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup	(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1584 
1585 		// Formats.
1586 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1587 		{
1588 			const string					filterGroupName = filterableFormatsByType[fmtNdx].name;
1589 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1590 
1591 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1592 			{
1593 				const Sampler::FilterMode			minFilter		= minFilterModes[filterNdx].mode;
1594 				const char* const					filterName		= minFilterModes[filterNdx].name;
1595 				const bool							isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1596 				const char* const					formatName		= filterableFormatsByType[fmtNdx].name;
1597 				const string						name			= string(formatName) + "_" + filterName;
1598 				Texture2DArrayTestCaseParameters	testParameters;
1599 
1600 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1601 				testParameters.minFilter	= minFilter;
1602 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1603 
1604 				testParameters.wrapS		= Sampler::REPEAT_GL;
1605 				testParameters.wrapT		= Sampler::REPEAT_GL;
1606 				testParameters.width		= 128;
1607 				testParameters.height		= 128;
1608 				testParameters.numLayers	= 8;
1609 
1610 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1611 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2DArray);
1612 
1613 				// Some tests have to be skipped due to the restrictions of the verifiers.
1614 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1615 				{
1616 					filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1617 				}
1618 			}
1619 			formatsGroup->addChild(filterGroup.release());
1620 		}
1621 
1622 		// Sizes.
1623 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2DArray); sizeNdx++)
1624 		{
1625 			const string					filterGroupName = de::toString(sizes2DArray[sizeNdx].width) + "x" + de::toString(sizes2DArray[sizeNdx].height) + "x" + de::toString(sizes2DArray[sizeNdx].numLayers);
1626 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1627 
1628 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1629 			{
1630 				const Sampler::FilterMode			minFilter		= minFilterModes[filterNdx].mode;
1631 				const char* const					filterName		= minFilterModes[filterNdx].name;
1632 				const bool							isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1633 				const string						name			= filterName;
1634 				Texture2DArrayTestCaseParameters	testParameters;
1635 
1636 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1637 				testParameters.minFilter	= minFilter;
1638 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1639 				testParameters.wrapS		= Sampler::REPEAT_GL;
1640 				testParameters.wrapT		= Sampler::REPEAT_GL;
1641 				testParameters.width		= sizes2DArray[sizeNdx].width;
1642 				testParameters.height		= sizes2DArray[sizeNdx].height;
1643 				testParameters.numLayers	= sizes2DArray[sizeNdx].numLayers;
1644 
1645 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1646 				testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1647 
1648 				filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1649 			}
1650 			sizesGroup->addChild(filterGroup.release());
1651 		}
1652 
1653 		// Wrap modes.
1654 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1655 		{
1656 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1657 
1658 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1659 			{
1660 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1661 
1662 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1663 				{
1664 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1665 
1666 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1667 					{
1668 						const string						name			= wrapModes[wrapTNdx].name;
1669 						Texture2DArrayTestCaseParameters	testParameters;
1670 
1671 						testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1672 						testParameters.minFilter	= minFilterModes[minFilterNdx].mode;
1673 						testParameters.magFilter	= magFilterModes[magFilterNdx].mode;
1674 						testParameters.wrapS		= wrapModes[wrapSNdx].mode;
1675 						testParameters.wrapT		= wrapModes[wrapTNdx].mode;
1676 						testParameters.width		= 123;
1677 						testParameters.height		= 107;
1678 						testParameters.numLayers	= 7;
1679 
1680 						testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1681 						testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1682 
1683 						wrapSGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1684 					}
1685 					magFilterGroup->addChild(wrapSGroup.release());
1686 				}
1687 				minFilterGroup->addChild(magFilterGroup.release());
1688 			}
1689 			combinationsGroup->addChild(minFilterGroup.release());
1690 		}
1691 
1692 		group2DArray->addChild(formatsGroup.release());
1693 		group2DArray->addChild(sizesGroup.release());
1694 		group2DArray->addChild(combinationsGroup.release());
1695 
1696 		textureFilteringTests->addChild(group2DArray.release());
1697 	}
1698 
1699 	// 3D texture filtering.
1700 	{
1701 		de::MovePtr<tcu::TestCaseGroup>	group3D				(new tcu::TestCaseGroup(testCtx, "3d", "3D Texture Filtering"));
1702 
1703 		de::MovePtr<tcu::TestCaseGroup>	formatsGroup		(new tcu::TestCaseGroup(testCtx, "formats", "3D Texture Formats"));
1704 		de::MovePtr<tcu::TestCaseGroup>	sizesGroup			(new tcu::TestCaseGroup(testCtx, "sizes", "Texture Sizes"));
1705 		de::MovePtr<tcu::TestCaseGroup>	combinationsGroup	(new tcu::TestCaseGroup(testCtx, "combinations", "Filter and wrap mode combinations"));
1706 
1707 		// Formats.
1708 		for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1709 		{
1710 			const string					filterGroupName = filterableFormatsByType[fmtNdx].name;
1711 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1712 
1713 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1714 			{
1715 				const Sampler::FilterMode	minFilter		= minFilterModes[filterNdx].mode;
1716 				const char* const			filterName		= minFilterModes[filterNdx].name;
1717 				const bool					isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1718 				const char* const			formatName		= filterableFormatsByType[fmtNdx].name;
1719 				const string				name			= string(formatName) + "_" + filterName;
1720 				Texture3DTestCaseParameters	testParameters;
1721 
1722 				testParameters.format		= filterableFormatsByType[fmtNdx].format;
1723 				testParameters.minFilter	= minFilter;
1724 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1725 
1726 				testParameters.wrapS		= Sampler::REPEAT_GL;
1727 				testParameters.wrapT		= Sampler::REPEAT_GL;
1728 				testParameters.wrapR		= Sampler::REPEAT_GL;
1729 				testParameters.width		= 64;
1730 				testParameters.height		= 64;
1731 				testParameters.depth		= 64;
1732 
1733 				testParameters.aspectMask	= filterableFormatsByType[fmtNdx].aspectMask;
1734 				testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program3D);
1735 
1736 				// Some tests have to be skipped due to the restrictions of the verifiers.
1737 				if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1738 				{
1739 					filterGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1740 				}
1741 			}
1742 			formatsGroup->addChild(filterGroup.release());
1743 		}
1744 
1745 		// Sizes.
1746 		for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes3D); sizeNdx++)
1747 		{
1748 			const string					filterGroupName = de::toString(sizes3D[sizeNdx].width) + "x" + de::toString(sizes3D[sizeNdx].height) + "x" + de::toString(sizes3D[sizeNdx].depth);
1749 			de::MovePtr<tcu::TestCaseGroup>	filterGroup		(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str(), ""));
1750 
1751 			for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1752 			{
1753 				const Sampler::FilterMode		minFilter		= minFilterModes[filterNdx].mode;
1754 				const char* const				filterName		= minFilterModes[filterNdx].name;
1755 				const bool						isMipmap		= minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1756 				const string					name			= filterName;
1757 				Texture3DTestCaseParameters		testParameters;
1758 
1759 				testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1760 				testParameters.minFilter	= minFilter;
1761 				testParameters.magFilter	= isMipmap ? Sampler::LINEAR : minFilter;
1762 				testParameters.wrapS		= Sampler::REPEAT_GL;
1763 				testParameters.wrapT		= Sampler::REPEAT_GL;
1764 				testParameters.wrapR		= Sampler::REPEAT_GL;
1765 				testParameters.width		= sizes3D[sizeNdx].width;
1766 				testParameters.height		= sizes3D[sizeNdx].height;
1767 				testParameters.depth		= sizes3D[sizeNdx].depth;
1768 
1769 				testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1770 				testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1771 
1772 				filterGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1773 			}
1774 			sizesGroup->addChild(filterGroup.release());
1775 		}
1776 
1777 		// Wrap modes.
1778 		for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1779 		{
1780 			de::MovePtr<tcu::TestCaseGroup>	minFilterGroup(new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name, ""));
1781 
1782 			for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1783 			{
1784 				de::MovePtr<tcu::TestCaseGroup>	magFilterGroup(new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name, ""));
1785 
1786 				for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1787 				{
1788 					de::MovePtr<tcu::TestCaseGroup>	wrapSGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name, ""));
1789 
1790 					for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1791 					{
1792 						de::MovePtr<tcu::TestCaseGroup>	wrapTGroup(new tcu::TestCaseGroup(testCtx, wrapModes[wrapTNdx].name, ""));
1793 
1794 						for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
1795 						{
1796 							const string				name			= wrapModes[wrapRNdx].name;
1797 							Texture3DTestCaseParameters	testParameters;
1798 
1799 							testParameters.format		= VK_FORMAT_R8G8B8A8_UNORM;
1800 							testParameters.minFilter	= minFilterModes[minFilterNdx].mode;
1801 							testParameters.magFilter	= magFilterModes[magFilterNdx].mode;
1802 							testParameters.wrapS		= wrapModes[wrapSNdx].mode;
1803 							testParameters.wrapT		= wrapModes[wrapTNdx].mode;
1804 							testParameters.wrapR		= wrapModes[wrapRNdx].mode;
1805 							testParameters.width		= 63;
1806 							testParameters.height		= 57;
1807 							testParameters.depth		= 67;
1808 
1809 							testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
1810 							testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1811 
1812 							wrapTGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), "", testParameters));
1813 						}
1814 						wrapSGroup->addChild(wrapTGroup.release());
1815 					}
1816 					magFilterGroup->addChild(wrapSGroup.release());
1817 				}
1818 				minFilterGroup->addChild(magFilterGroup.release());
1819 			}
1820 			combinationsGroup->addChild(minFilterGroup.release());
1821 		}
1822 
1823 		group3D->addChild(formatsGroup.release());
1824 		group3D->addChild(sizesGroup.release());
1825 		group3D->addChild(combinationsGroup.release());
1826 
1827 		textureFilteringTests->addChild(group3D.release());
1828 	}
1829 }
1830 
createTextureFilteringTests(tcu::TestContext & testCtx)1831 tcu::TestCaseGroup*	createTextureFilteringTests	(tcu::TestContext& testCtx)
1832 {
1833 	return createTestGroup(testCtx, "filtering", "Texture filtering tests.", populateTextureFilteringTests);
1834 }
1835 
1836 } // texture
1837 } // vkt
1838