• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
7  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Shadow texture lookup tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktTextureShadowTests.hpp"
27 
28 #include "deMath.h"
29 #include "deString.h"
30 #include "deStringUtil.hpp"
31 #include "gluPixelTransfer.hpp"
32 #include "gluTextureTestUtil.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuImageIO.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTexCompareVerifier.hpp"
38 #include "tcuTexVerifierUtil.hpp"
39 #include "tcuTexture.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "vkImageUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vktTestGroupUtil.hpp"
44 #include "vktTextureTestUtil.hpp"
45 
46 using namespace vk;
47 
48 namespace vkt
49 {
50 namespace texture
51 {
52 namespace
53 {
54 
55 using std::vector;
56 using std::string;
57 using tcu::TestLog;
58 using tcu::Sampler;
59 using namespace texture::util;
60 using namespace glu::TextureTestUtil;
61 
62 enum
63 {
64 	TEXCUBE_VIEWPORT_SIZE	= 28,
65 	TEX1D_VIEWPORT_WIDTH	= 64,
66 	TEX2D_VIEWPORT_WIDTH	= 64,
67 	TEX2D_VIEWPORT_HEIGHT	= 64
68 };
69 
70 struct TextureShadowCommonTestCaseParameters
71 {
72 										TextureShadowCommonTestCaseParameters	(void);
73 	Sampler::CompareMode				compareOp;
74 	TextureBinding::ImageBackingMode	backingMode;
75 };
76 
TextureShadowCommonTestCaseParameters(void)77 TextureShadowCommonTestCaseParameters::TextureShadowCommonTestCaseParameters (void)
78 	: compareOp							(Sampler::COMPAREMODE_EQUAL)
79 	, backingMode						(TextureBinding::IMAGE_BACKING_MODE_REGULAR)
80 {
81 }
82 
83 struct Texture2DShadowTestCaseParameters : public Texture2DTestCaseParameters, public TextureShadowCommonTestCaseParameters
84 {
85 };
86 
isFloatingPointDepthFormat(const tcu::TextureFormat & format)87 bool isFloatingPointDepthFormat (const tcu::TextureFormat& format)
88 {
89 	// Only two depth and depth-stencil formats are floating point
90 	return	(format.order == tcu::TextureFormat::D && format.type == tcu::TextureFormat::FLOAT) ||
91 			(format.order == tcu::TextureFormat::DS && format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV);
92 }
93 
clampFloatingPointTexture(const tcu::PixelBufferAccess & access)94 void clampFloatingPointTexture (const tcu::PixelBufferAccess& access)
95 {
96 	DE_ASSERT(isFloatingPointDepthFormat(access.getFormat()));
97 
98 	for (int z = 0; z < access.getDepth(); ++z)
99 	for (int y = 0; y < access.getHeight(); ++y)
100 	for (int x = 0; x < access.getWidth(); ++x)
101 		access.setPixDepth(de::clamp(access.getPixDepth(x, y, z), 0.0f, 1.0f), x, y, z);
102 }
103 
clampFloatingPointTexture(tcu::Texture2D & target)104 void clampFloatingPointTexture (tcu::Texture2D& target)
105 {
106 	for (int level = 0; level < target.getNumLevels(); ++level)
107 		if (!target.isLevelEmpty(level))
108 			clampFloatingPointTexture(target.getLevel(level));
109 }
110 
clampFloatingPointTexture(tcu::Texture2DArray & target)111 static void clampFloatingPointTexture (tcu::Texture2DArray& target)
112 {
113 	for (int level = 0; level < target.getNumLevels(); ++level)
114 		if (!target.isLevelEmpty(level))
115 			clampFloatingPointTexture(target.getLevel(level));
116 }
117 
clampFloatingPointTexture(tcu::TextureCube & target)118 void clampFloatingPointTexture (tcu::TextureCube& target)
119 {
120 	for (int level = 0; level < target.getNumLevels(); ++level)
121 		for (int face = tcu::CUBEFACE_NEGATIVE_X; face < tcu::CUBEFACE_LAST; ++face)
122 			clampFloatingPointTexture(target.getLevelFace(level, (tcu::CubeFace)face));
123 }
124 
clampFloatingPointTexture(tcu::Texture1D & target)125 void clampFloatingPointTexture (tcu::Texture1D& target)
126 {
127 	for (int level = 0; level < target.getNumLevels(); ++level)
128 		if (!target.isLevelEmpty(level))
129 			clampFloatingPointTexture(target.getLevel(level));
130 }
131 
clampFloatingPointTexture(tcu::Texture1DArray & target)132 static void clampFloatingPointTexture (tcu::Texture1DArray& target)
133 {
134 	for (int level = 0; level < target.getNumLevels(); ++level)
135 		if (!target.isLevelEmpty(level))
136 			clampFloatingPointTexture(target.getLevel(level));
137 }
138 
clampFloatingPointTexture(tcu::TextureCubeArray & target)139 void clampFloatingPointTexture (tcu::TextureCubeArray& target)
140 {
141 	for (int level = 0; level < target.getNumLevels(); ++level)
142 		clampFloatingPointTexture(target.getLevel(level)); // face and layer are inside level's depth
143 }
144 
getPixelFormat(tcu::TextureFormat texFormat)145 tcu::PixelFormat getPixelFormat(tcu::TextureFormat texFormat)
146 {
147 	const tcu::IVec4			formatBitDepth		= tcu::getTextureFormatBitDepth(tcu::getEffectiveDepthStencilTextureFormat(texFormat, Sampler::MODE_DEPTH));
148 	return tcu::PixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
149 }
150 
151 template<typename TextureType>
verifyTexCompareResult(tcu::TestContext & testCtx,const tcu::ConstPixelBufferAccess & result,const TextureType & src,const float * texCoord,const ReferenceParams & sampleParams,const tcu::TexComparePrecision & comparePrec,const tcu::LodPrecision & lodPrec,const tcu::PixelFormat & pixelFormat)152 bool verifyTexCompareResult (tcu::TestContext&						testCtx,
153 							 const tcu::ConstPixelBufferAccess&		result,
154 							 const TextureType&						src,
155 							 const float*							texCoord,
156 							 const ReferenceParams&					sampleParams,
157 							 const tcu::TexComparePrecision&		comparePrec,
158 							 const tcu::LodPrecision&				lodPrec,
159 							 const tcu::PixelFormat&				pixelFormat)
160 {
161 	tcu::TestLog&	log					= testCtx.getLog();
162 	tcu::Surface	reference			(result.getWidth(), result.getHeight());
163 	tcu::Surface	errorMask			(result.getWidth(), result.getHeight());
164 	const tcu::Vec3	nonShadowThreshold	= tcu::computeFixedPointThreshold(getBitsVec(pixelFormat)-1).swizzle(1,2,3);
165 	int				numFailedPixels;
166 
167 	// sampleTexture() expects source image to be the same state as it would be in a GL implementation, that is
168 	// the floating point depth values should be in [0, 1] range as data is clamped during texture upload. Since
169 	// we don't have a separate "uploading" phase and just reuse the buffer we used for GL-upload, do the clamping
170 	// here if necessary.
171 
172 	if (isFloatingPointDepthFormat(src.getFormat()))
173 	{
174 		TextureType clampedSource(src);
175 
176 		clampFloatingPointTexture(clampedSource);
177 
178 		// sample clamped values
179 
180 		sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), clampedSource, texCoord, sampleParams);
181 		numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), clampedSource, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold);
182 	}
183 	else
184 	{
185 		// sample raw values (they are guaranteed to be in [0, 1] range as the format cannot represent any other values)
186 
187 		sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), src, texCoord, sampleParams);
188 		numFailedPixels = computeTextureCompareDiff(result, reference.getAccess(), errorMask.getAccess(), src, texCoord, sampleParams, comparePrec, lodPrec, nonShadowThreshold);
189 	}
190 
191 	if (numFailedPixels > 0)
192 		log << TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
193 
194 	log << TestLog::ImageSet("VerifyResult", "Verification result")
195 		<< TestLog::Image("Rendered", "Rendered image", result);
196 
197 	if (numFailedPixels > 0)
198 	{
199 		log << TestLog::Image("Reference", "Ideal reference image", reference)
200 			<< TestLog::Image("ErrorMask", "Error mask", errorMask);
201 	}
202 
203 	log << TestLog::EndImageSet;
204 
205 	return numFailedPixels == 0;
206 }
207 
checkTextureSupport(Context & context,const Texture2DShadowTestCaseParameters & testParameters)208 void checkTextureSupport (Context& context, const Texture2DShadowTestCaseParameters& testParameters)
209 {
210 	const VkFormatProperties3KHR formatProperties = context.getFormatProperties(testParameters.format);
211 	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
212 		TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
213 }
214 
215 class Texture2DShadowTestInstance : public TestInstance
216 {
217 public:
218 	typedef Texture2DShadowTestCaseParameters	ParameterType;
219 												Texture2DShadowTestInstance		(Context& context, const ParameterType& testParameters);
220 												~Texture2DShadowTestInstance	(void);
221 
222 	virtual tcu::TestStatus						iterate							(void);
223 
224 private:
225 												Texture2DShadowTestInstance		(const Texture2DShadowTestInstance& other);
226 	Texture2DShadowTestInstance&				operator=						(const Texture2DShadowTestInstance& other);
227 
228 	struct FilterCase
229 	{
230 		int			textureIndex;
231 
232 		tcu::Vec2	minCoord;
233 		tcu::Vec2	maxCoord;
234 		float		ref;
235 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture2DShadowTestInstance::FilterCase236 		FilterCase	(void)
237 			: textureIndex(-1)
238 			, ref		(0.0f)
239 		{
240 		}
241 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture2DShadowTestInstance::FilterCase242 		FilterCase	(int tex_, const float ref_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
243 			: textureIndex	(tex_)
244 			, minCoord		(minCoord_)
245 			, maxCoord		(maxCoord_)
246 			, ref			(ref_)
247 		{
248 		}
249 	};
250 
251 	const ParameterType&			m_testParameters;
252 	std::vector<TestTexture2DSp>	m_textures;
253 	std::vector<FilterCase>			m_cases;
254 
255 	TextureRenderer					m_renderer;
256 
257 	int								m_caseNdx;
258 };
259 
Texture2DShadowTestInstance(Context & context,const ParameterType & testParameters)260 Texture2DShadowTestInstance::Texture2DShadowTestInstance (Context& context, const ParameterType& testParameters)
261 	: TestInstance			(context)
262 	, m_testParameters		(testParameters)
263 	, m_renderer			(context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
264 	, m_caseNdx				(0)
265 {
266 	// Create 2 textures.
267 	m_textures.reserve(2);
268 	for (int ndx = 0; ndx < 2; ndx++)
269 	{
270 		m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
271 	}
272 
273 	const int	numLevels	= m_textures[0]->getNumLevels();
274 
275 	// Fill first gradient texture.
276 	for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
277 	{
278 		tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
279 	}
280 
281 	// Fill second with grid texture.
282 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
283 	{
284 		const deUint32	step	= 0x00ffffff / numLevels;
285 		const deUint32	rgb		= step*levelNdx;
286 		const deUint32	colorA	= 0xff000000 | rgb;
287 		const deUint32	colorB	= 0xff000000 | ~rgb;
288 
289 		tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec(), tcu::RGBA(colorB).toVec());
290 	}
291 
292 	// Upload.
293 	for (std::vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
294 	{
295 		m_renderer.add2DTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
296 	}
297 
298 	// Compute cases.
299 	{
300 		const float refInRangeUpper		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
301 		const float refInRangeLower		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
302 		const float refOutOfBoundsUpper	= 1.1f;		// !< lookup function should clamp values to [0, 1] range
303 		const float refOutOfBoundsLower	= -0.1f;
304 
305 		const struct
306 		{
307 			const int	texNdx;
308 			const float	ref;
309 			const float	lodX;
310 			const float	lodY;
311 			const float	oX;
312 			const float	oY;
313 		} cases[] =
314 		{
315 			{ 0,	refInRangeUpper,		1.6f,	2.9f,	-1.0f,	-2.7f	},
316 			{ 0,	refInRangeLower,		-2.0f,	-1.35f,	-0.2f,	0.7f	},
317 			{ 1,	refInRangeUpper,		0.14f,	0.275f,	-1.5f,	-1.1f	},
318 			{ 1,	refInRangeLower,		-0.92f,	-2.64f,	0.4f,	-0.1f	},
319 			{ 1,	refOutOfBoundsUpper,	-0.39f,	-0.52f,	0.65f,	0.87f	},
320 			{ 1,	refOutOfBoundsLower,	-1.55f,	0.65f,	0.35f,	0.91f	},
321 		};
322 
323 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
324 		{
325 			const int	texNdx	= de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
326 			const float ref		= cases[caseNdx].ref;
327 			const float	lodX	= cases[caseNdx].lodX;
328 			const float	lodY	= cases[caseNdx].lodY;
329 			const float	oX		= cases[caseNdx].oX;
330 			const float	oY		= cases[caseNdx].oY;
331 			const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
332 			const float	sY		= deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[texNdx]->getTexture().getHeight());
333 
334 			m_cases.push_back(FilterCase(texNdx, ref, tcu::Vec2(oX, oY), tcu::Vec2(oX+sX, oY+sY)));
335 		}
336 	}
337 
338 	m_caseNdx = 0;
339 }
340 
~Texture2DShadowTestInstance(void)341 Texture2DShadowTestInstance::~Texture2DShadowTestInstance (void)
342 {
343 	m_textures.clear();
344 	m_cases.clear();
345 }
346 
iterate(void)347 tcu::TestStatus Texture2DShadowTestInstance::iterate (void)
348 {
349 	tcu::TestLog&					log				= m_context.getTestContext().getLog();
350 	const pipeline::TestTexture2D&	texture			= m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
351 	const tcu::TextureFormat		texFmt			= texture.getTextureFormat();
352 	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
353 	const tcu::ScopedLogSection		section			(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
354 
355 	const FilterCase&				curCase			= m_cases[m_caseNdx];
356 	ReferenceParams					sampleParams	(TEXTURETYPE_2D);
357 	tcu::Surface					rendered		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
358 	vector<float>					texCoord;
359 
360 	// Setup params for reference.
361 	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
362 	sampleParams.sampler.compare	= m_testParameters.compareOp;
363 	sampleParams.samplerType		= SAMPLERTYPE_SHADOW;
364 	sampleParams.lodMode			= LODMODE_EXACT;
365 	sampleParams.colorBias			= fmtInfo.lookupBias;
366 	sampleParams.colorScale			= fmtInfo.lookupScale;
367 	sampleParams.ref				= curCase.ref;
368 
369 	log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
370 
371 	// Compute texture coordinates.
372 	log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
373 	computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
374 
375 	m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
376 
377 	{
378 		const tcu::PixelFormat		pixelFormat			= getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
379 		tcu::LodPrecision			lodPrecision;
380 		tcu::TexComparePrecision	texComparePrecision;
381 
382 		lodPrecision.derivateBits			= 18;
383 		lodPrecision.lodBits				= 6;
384 		texComparePrecision.coordBits		= tcu::IVec3(20,20,0);
385 		texComparePrecision.uvwBits			= tcu::IVec3(7,7,0);
386 		texComparePrecision.pcfBits			= 5;
387 		texComparePrecision.referenceBits	= 16;
388 		texComparePrecision.resultBits		= pixelFormat.redBits-1;
389 
390 		const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
391 														  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
392 
393 		if (!isHighQuality)
394 		{
395 			m_context.getTestContext().getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
396 
397 			lodPrecision.lodBits			= 4;
398 			texComparePrecision.uvwBits		= tcu::IVec3(4,4,0);
399 			texComparePrecision.pcfBits		= 0;
400 
401 			const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
402 													 &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
403 
404 			if (!isOk)
405 			{
406 				m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
407 				return tcu::TestStatus::fail("Image verification failed");
408 			}
409 		}
410 	}
411 
412 	m_caseNdx += 1;
413 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
414 }
415 
416 struct TextureCubeShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public TextureCubeTestCaseParameters
417 {
418 };
419 
checkTextureSupport(Context & context,const TextureCubeShadowTestCaseParameters & testParameters)420 void checkTextureSupport (Context& context, const TextureCubeShadowTestCaseParameters& testParameters)
421 {
422 	const VkFormatProperties3KHR formatProperties = context.getFormatProperties(testParameters.format);
423 	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
424 		TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
425 }
426 
427 
428 class TextureCubeShadowTestInstance : public TestInstance
429 {
430 public:
431 	typedef TextureCubeShadowTestCaseParameters ParameterType;
432 												TextureCubeShadowTestInstance		(Context& context, const ParameterType& testParameters);
433 												~TextureCubeShadowTestInstance		(void);
434 
435 	virtual tcu::TestStatus						iterate								(void);
436 
437 private:
438 												TextureCubeShadowTestInstance		(const TextureCubeShadowTestInstance& other);
439 	TextureCubeShadowTestInstance&				operator=							(const TextureCubeShadowTestInstance& other);
440 
441 	struct FilterCase
442 	{
443 		int						textureIndex;
444 		tcu::Vec2				bottomLeft;
445 		tcu::Vec2				topRight;
446 		float					ref;
447 
FilterCasevkt::texture::__anon26fa1f1d0111::TextureCubeShadowTestInstance::FilterCase448 		FilterCase (void)
449 			: textureIndex	(-1)
450 			, ref			(0.0f)
451 		{
452 		}
453 
FilterCasevkt::texture::__anon26fa1f1d0111::TextureCubeShadowTestInstance::FilterCase454 		FilterCase (const int tex_, const float ref_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
455 			: textureIndex	(tex_)
456 			, bottomLeft	(bottomLeft_)
457 			, topRight		(topRight_)
458 			, ref			(ref_)
459 		{
460 		}
461 	};
462 
463 	const ParameterType&		m_testParameters;
464 	vector<TestTextureCubeSp>	m_textures;
465 	std::vector<FilterCase>		m_cases;
466 
467 	TextureRenderer				m_renderer;
468 	int							m_caseNdx;
469 };
470 
TextureCubeShadowTestInstance(Context & context,const ParameterType & testParameters)471 TextureCubeShadowTestInstance::TextureCubeShadowTestInstance (Context& context, const ParameterType& testParameters)
472 	: TestInstance			(context)
473 	, m_testParameters		(testParameters)
474 	, m_renderer			(context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
475 	, m_caseNdx				(0)
476 {
477 	const int						numLevels	= deLog2Floor32(m_testParameters.size)+1;
478 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
479 	const tcu::Vec4					cBias		= fmtInfo.valueMin;
480 	const tcu::Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
481 
482 	// Create textures.
483 
484 	m_textures.reserve(2);
485 	for (int ndx = 0; ndx < 2; ndx++)
486 	{
487 		m_textures.push_back(TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
488 	}
489 
490 	// Fill first with gradient texture.
491 	static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
492 	{
493 		{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
494 		{ tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
495 		{ tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
496 		{ tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
497 		{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
498 		{ tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
499 	};
500 
501 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
502 	{
503 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
504 		{
505 			tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
506 		}
507 	}
508 
509 	// Fill second with grid texture.
510 	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
511 	{
512 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
513 		{
514 			const deUint32	step	= 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
515 			const deUint32	rgb		= step*levelNdx*face;
516 			const deUint32	colorA	= 0xff000000 | rgb;
517 			const deUint32	colorB	= 0xff000000 | ~rgb;
518 
519 			tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
520 		}
521 	}
522 
523 	// Upload.
524 	for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
525 	{
526 		m_renderer.addCubeTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
527 	}
528 
529 	// Compute cases
530 	{
531 		const float refInRangeUpper		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
532 		const float refInRangeLower		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
533 		const float refOutOfBoundsUpper	= 1.1f;
534 		const float refOutOfBoundsLower	= -0.1f;
535 
536 		m_cases.push_back(FilterCase(0,	refInRangeUpper,		tcu::Vec2(-1.25f, -1.2f),	tcu::Vec2(1.2f, 1.25f)));	// minification
537 		m_cases.push_back(FilterCase(0,	refInRangeLower,		tcu::Vec2(0.8f, 0.8f),		tcu::Vec2(1.25f, 1.20f)));	// magnification
538 		m_cases.push_back(FilterCase(1,	refInRangeUpper,		tcu::Vec2(-1.19f, -1.3f),	tcu::Vec2(1.1f, 1.35f)));	// minification
539 		m_cases.push_back(FilterCase(1,	refInRangeLower,		tcu::Vec2(-1.2f, -1.1f),	tcu::Vec2(-0.8f, -0.8f)));	// magnification
540 		m_cases.push_back(FilterCase(1,	refOutOfBoundsUpper,	tcu::Vec2(-0.61f, -0.1f),	tcu::Vec2(0.9f, 1.18f)));	// reference value clamp, upper
541 		m_cases.push_back(FilterCase(1,	refOutOfBoundsLower,	tcu::Vec2(-0.75f, 1.0f),	tcu::Vec2(0.05f, 0.75f)));	// reference value clamp, lower
542 	}
543 }
544 
~TextureCubeShadowTestInstance(void)545 TextureCubeShadowTestInstance::~TextureCubeShadowTestInstance	(void)
546 {
547 }
548 
getFaceDesc(const tcu::CubeFace face)549 static const char* getFaceDesc (const tcu::CubeFace face)
550 {
551 	switch (face)
552 	{
553 		case tcu::CUBEFACE_NEGATIVE_X:	return "-X";
554 		case tcu::CUBEFACE_POSITIVE_X:	return "+X";
555 		case tcu::CUBEFACE_NEGATIVE_Y:	return "-Y";
556 		case tcu::CUBEFACE_POSITIVE_Y:	return "+Y";
557 		case tcu::CUBEFACE_NEGATIVE_Z:	return "-Z";
558 		case tcu::CUBEFACE_POSITIVE_Z:	return "+Z";
559 		default:
560 			DE_ASSERT(false);
561 			return DE_NULL;
562 	}
563 }
564 
iterate(void)565 tcu::TestStatus TextureCubeShadowTestInstance::iterate (void)
566 {
567 
568 	tcu::TestLog&						log				= m_context.getTestContext().getLog();
569 	const tcu::ScopedLogSection			iterSection		(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
570 	const FilterCase&					curCase			= m_cases[m_caseNdx];
571 	const pipeline::TestTextureCube&	texture			= m_renderer.getCubeTexture(curCase.textureIndex);
572 
573 	ReferenceParams						sampleParams	(TEXTURETYPE_CUBE);
574 
575 	// Params for reference computation.
576 	sampleParams.sampler					= util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
577 	sampleParams.sampler.seamlessCubeMap	= true;
578 	sampleParams.sampler.compare			= m_testParameters.compareOp;
579 	sampleParams.samplerType				= SAMPLERTYPE_SHADOW;
580 	sampleParams.lodMode					= LODMODE_EXACT;
581 	sampleParams.ref						= curCase.ref;
582 
583 	log	<< TestLog::Message
584 		<< "Compare reference value = " << sampleParams.ref << "\n"
585 		<< "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
586 		<< TestLog::EndMessage;
587 
588 	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
589 	{
590 		const tcu::CubeFace		face		= tcu::CubeFace(faceNdx);
591 		tcu::Surface			result		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
592 		vector<float>			texCoord;
593 
594 		computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
595 
596 		log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
597 
598 		// \todo Log texture coordinates.
599 
600 		m_renderer.renderQuad(result, curCase.textureIndex, &texCoord[0], sampleParams);
601 
602 		{
603 			const tcu::PixelFormat		pixelFormat			= getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
604 			tcu::LodPrecision			lodPrecision;
605 			tcu::TexComparePrecision	texComparePrecision;
606 
607 			lodPrecision.derivateBits			= 10;
608 			lodPrecision.lodBits				= 5;
609 			texComparePrecision.coordBits		= tcu::IVec3(10,10,10);
610 			texComparePrecision.uvwBits			= tcu::IVec3(6,6,0);
611 			texComparePrecision.pcfBits			= 5;
612 			texComparePrecision.referenceBits	= 16;
613 			texComparePrecision.resultBits		= pixelFormat.redBits-1;
614 
615 			const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
616 															  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
617 
618 			if (!isHighQuality)
619 			{
620 				log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
621 
622 				lodPrecision.lodBits			= 4;
623 				texComparePrecision.uvwBits		= tcu::IVec3(4,4,0);
624 				texComparePrecision.pcfBits		= 0;
625 
626 				const bool isOk = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
627 														 &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
628 
629 				if (!isOk)
630 				{
631 					log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
632 					return tcu::TestStatus::fail("Image verification failed");
633 				}
634 			}
635 		}
636 	}
637 
638 	m_caseNdx += 1;
639 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
640 }
641 
642 struct Texture2DArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public Texture2DArrayTestCaseParameters
643 {
644 };
645 
checkTextureSupport(Context & context,const Texture2DArrayShadowTestCaseParameters & testParameters)646 void checkTextureSupport (Context& context, const Texture2DArrayShadowTestCaseParameters& testParameters)
647 {
648 	const VkFormatProperties3KHR formatProperties = context.getFormatProperties(testParameters.format);
649 	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
650 		TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
651 }
652 
653 class Texture2DArrayShadowTestInstance : public TestInstance
654 {
655 public:
656 	typedef Texture2DArrayShadowTestCaseParameters	ParameterType;
657 													Texture2DArrayShadowTestInstance		(Context& context, const ParameterType& testParameters);
658 													~Texture2DArrayShadowTestInstance		(void);
659 
660 	virtual tcu::TestStatus							iterate									(void);
661 
662 private:
663 													Texture2DArrayShadowTestInstance		(const Texture2DArrayShadowTestInstance& other);
664 	Texture2DArrayShadowTestInstance&				operator=								(const Texture2DArrayShadowTestInstance& other);
665 
666 	struct FilterCase
667 	{
668 		int							textureIndex;
669 		tcu::Vec3					minCoord;
670 		tcu::Vec3					maxCoord;
671 		float						ref;
672 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture2DArrayShadowTestInstance::FilterCase673 		FilterCase (void)
674 			: textureIndex	(-1)
675 			, ref			(0.0f)
676 		{
677 		}
678 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture2DArrayShadowTestInstance::FilterCase679 		FilterCase (const int tex_, float ref_, const tcu::Vec3& minCoord_, const tcu::Vec3& maxCoord_)
680 			: textureIndex	(tex_)
681 			, minCoord		(minCoord_)
682 			, maxCoord		(maxCoord_)
683 			, ref			(ref_)
684 		{
685 		}
686 	};
687 
688 	const ParameterType&				m_testParameters;
689 	std::vector<TestTexture2DArraySp>	m_textures;
690 	std::vector<FilterCase>				m_cases;
691 
692 	TextureRenderer						m_renderer;
693 
694 	int									m_caseNdx;
695 };
696 
Texture2DArrayShadowTestInstance(Context & context,const ParameterType & testParameters)697 Texture2DArrayShadowTestInstance::Texture2DArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
698 	: TestInstance			(context)
699 	, m_testParameters		(testParameters)
700 	, m_renderer			(context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
701 	, m_caseNdx				(0)
702 {
703 	const int						numLevels	= deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height))+1;
704 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
705 	const tcu::Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
706 	const tcu::Vec4					cBias		= fmtInfo.valueMin;
707 
708 	// Create 2 textures.
709 	m_textures.reserve(2);
710 	for (int ndx = 0; ndx < 2; ndx++)
711 	{
712 		m_textures.push_back(TestTexture2DArraySp(new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, m_testParameters.numLayers)));
713 	}
714 
715 	// Fill first gradient texture.
716 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
717 	{
718 		const tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
719 		const tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
720 
721 		tcu::fillWithComponentGradients(m_textures[0]->getTexture().getLevel(levelNdx), gMin, gMax);
722 	}
723 
724 	// Fill second with grid texture.
725 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
726 	{
727 		const deUint32	step	= 0x00ffffff / numLevels;
728 		const deUint32	rgb		= step*levelNdx;
729 		const deUint32	colorA	= 0xff000000 | rgb;
730 		const deUint32	colorB	= 0xff000000 | ~rgb;
731 
732 		tcu::fillWithGrid(m_textures[1]->getTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
733 	}
734 
735 	// Upload.
736 	for (std::vector<TestTexture2DArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
737 	{
738 		m_renderer.add2DArrayTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
739 	}
740 
741 	// Compute cases.
742 	{
743 		const float refInRangeUpper		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 1.0f : 0.5f;
744 		const float refInRangeLower		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL) ? 0.0f : 0.5f;
745 		const float refOutOfBoundsUpper	= 1.1f;		// !< lookup function should clamp values to [0, 1] range
746 		const float refOutOfBoundsLower	= -0.1f;
747 
748 		const struct
749 		{
750 			const int	texNdx;
751 			const float	ref;
752 			const float	lodX;
753 			const float	lodY;
754 			const float	oX;
755 			const float	oY;
756 		} cases[] =
757 		{
758 			{ 0,	refInRangeUpper,		1.6f,	2.9f,	-1.0f,	-2.7f	},
759 			{ 0,	refInRangeLower,		-2.0f,	-1.35f,	-0.2f,	0.7f	},
760 			{ 1,	refInRangeUpper,		0.14f,	0.275f,	-1.5f,	-1.1f	},
761 			{ 1,	refInRangeLower,		-0.92f,	-2.64f,	0.4f,	-0.1f	},
762 			{ 1,	refOutOfBoundsUpper,	-0.49f,	-0.22f,	0.45f,	0.97f	},
763 			{ 1,	refOutOfBoundsLower,	-0.85f,	0.75f,	0.25f,	0.61f	},
764 		};
765 
766 		const float	minLayer	= -0.5f;
767 		const float	maxLayer	= (float)m_testParameters.numLayers;
768 
769 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
770 		{
771 			const int	tex		= cases[caseNdx].texNdx > 0 ? 1 : 0;
772 			const float	ref		= cases[caseNdx].ref;
773 			const float	lodX	= cases[caseNdx].lodX;
774 			const float	lodY	= cases[caseNdx].lodY;
775 			const float	oX		= cases[caseNdx].oX;
776 			const float	oY		= cases[caseNdx].oY;
777 			const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[tex]->getTexture().getWidth());
778 			const float	sY		= deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[tex]->getTexture().getHeight());
779 
780 			m_cases.push_back(FilterCase(tex, ref, tcu::Vec3(oX, oY, minLayer), tcu::Vec3(oX+sX, oY+sY, maxLayer)));
781 		}
782 	}
783 }
784 
~Texture2DArrayShadowTestInstance(void)785 Texture2DArrayShadowTestInstance::~Texture2DArrayShadowTestInstance (void)
786 {
787 }
788 
iterate(void)789 tcu::TestStatus Texture2DArrayShadowTestInstance::iterate (void)
790 {
791 	tcu::TestLog&						log				= m_context.getTestContext().getLog();
792 	const FilterCase&					curCase			= m_cases[m_caseNdx];
793 	const pipeline::TestTexture2DArray&	texture			= m_renderer.get2DArrayTexture(curCase.textureIndex);
794 
795 	ReferenceParams						sampleParams	(TEXTURETYPE_2D_ARRAY);
796 	tcu::Surface						rendered		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
797 	const tcu::ScopedLogSection			section			(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
798 
799 	const float							texCoord[]		=
800 	{
801 		curCase.minCoord.x(), curCase.minCoord.y(), curCase.minCoord.z(),
802 		curCase.minCoord.x(), curCase.maxCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f,
803 		curCase.maxCoord.x(), curCase.minCoord.y(), (curCase.minCoord.z() + curCase.maxCoord.z()) / 2.0f,
804 		curCase.maxCoord.x(), curCase.maxCoord.y(), curCase.maxCoord.z()
805 	};
806 
807 	// Setup params for reference.
808 	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
809 	sampleParams.sampler.compare	= m_testParameters.compareOp;
810 	sampleParams.samplerType		= SAMPLERTYPE_SHADOW;
811 	sampleParams.lodMode			= LODMODE_EXACT;
812 	sampleParams.ref				= curCase.ref;
813 
814 	log	<< TestLog::Message
815 		<< "Compare reference value = " << sampleParams.ref << "\n"
816 		<< "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
817 		<< TestLog::EndMessage;
818 
819 	m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
820 
821 	{
822 		const tcu::PixelFormat		pixelFormat			= getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
823 		tcu::LodPrecision			lodPrecision;
824 		tcu::TexComparePrecision	texComparePrecision;
825 
826 		lodPrecision.derivateBits			= 18;
827 		lodPrecision.lodBits				= 6;
828 		texComparePrecision.coordBits		= tcu::IVec3(20,20,20);
829 		texComparePrecision.uvwBits			= tcu::IVec3(7,7,7);
830 		texComparePrecision.pcfBits			= 5;
831 		texComparePrecision.referenceBits	= 16;
832 		texComparePrecision.resultBits		= pixelFormat.redBits-1;
833 
834 		const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
835 														  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
836 
837 		if (!isHighQuality)
838 		{
839 			log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
840 
841 			lodPrecision.lodBits			= 4;
842 			texComparePrecision.uvwBits		= tcu::IVec3(4,4,4);
843 			texComparePrecision.pcfBits		= 0;
844 
845 			const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
846 													 &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
847 
848 			if (!isOk)
849 			{
850 				log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
851 				return tcu::TestStatus::fail("Image verification failed");
852 			}
853 		}
854 	}
855 
856 	m_caseNdx += 1;
857 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
858 }
859 
860 struct Texture1DShadowTestCaseParameters : public Texture1DTestCaseParameters, public TextureShadowCommonTestCaseParameters
861 {
862 };
863 
checkTextureSupport(Context & context,const Texture1DShadowTestCaseParameters & testParameters)864 void checkTextureSupport (Context& context, const Texture1DShadowTestCaseParameters& testParameters)
865 {
866 	const VkFormatProperties3KHR formatProperties = context.getFormatProperties(testParameters.format);
867 	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
868 		TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
869 }
870 
871 class Texture1DShadowTestInstance : public TestInstance
872 {
873 public:
874 	typedef Texture1DShadowTestCaseParameters	ParameterType;
875 												Texture1DShadowTestInstance		(Context& context, const ParameterType& testParameters);
876 												~Texture1DShadowTestInstance	(void);
877 
878 	virtual tcu::TestStatus						iterate							(void);
879 
880 private:
881 												Texture1DShadowTestInstance		(const Texture1DShadowTestInstance& other) = delete;
882 	Texture1DShadowTestInstance&				operator=						(const Texture1DShadowTestInstance& other) = delete;
883 
884 	struct FilterCase
885 	{
886 		int			textureIndex;
887 
888 		float		minCoord;
889 		float		maxCoord;
890 		float		ref;
891 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture1DShadowTestInstance::FilterCase892 		FilterCase	(void)
893 			: textureIndex(-1)
894 			, minCoord	(0)
895 			, maxCoord	(0)
896 			, ref		(0.0f)
897 		{
898 		}
899 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture1DShadowTestInstance::FilterCase900 		FilterCase	(int tex_, const float ref_, const float& minCoord_, const float& maxCoord_)
901 			: textureIndex	(tex_)
902 			, minCoord		(minCoord_)
903 			, maxCoord		(maxCoord_)
904 			, ref			(ref_)
905 		{
906 		}
907 	};
908 
909 	const ParameterType&			m_testParameters;
910 	std::vector<TestTexture1DSp>	m_textures;
911 	std::vector<FilterCase>			m_cases;
912 
913 	TextureRenderer					m_renderer;
914 
915 	int								m_caseNdx;
916 };
917 
Texture1DShadowTestInstance(Context & context,const ParameterType & testParameters)918 Texture1DShadowTestInstance::Texture1DShadowTestInstance (Context& context, const ParameterType& testParameters)
919 	: TestInstance			(context)
920 	, m_testParameters		(testParameters)
921 	, m_renderer			(context, testParameters.sampleCount, TEX1D_VIEWPORT_WIDTH, 1, 1, vk::makeComponentMappingRGBA(), vk::VK_IMAGE_TYPE_1D, vk::VK_IMAGE_VIEW_TYPE_1D)
922 	, m_caseNdx				(0)
923 {
924 	// Create 2 textures.
925 	m_textures.reserve(2);
926 	for (int ndx = 0; ndx < 2; ndx++)
927 	{
928 		m_textures.push_back(TestTexture1DSp(new pipeline::TestTexture1D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width)));
929 	}
930 
931 	const int	numLevels	= m_textures[0]->getNumLevels();
932 
933 	// Fill first gradient texture.
934 	for (int levelNdx = 0; levelNdx < numLevels; ++levelNdx)
935 	{
936 		tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
937 	}
938 
939 	// Fill second with grid texture.
940 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
941 	{
942 		const deUint32	step	= 0x00ffffff / numLevels;
943 		const deUint32	rgb		= step*levelNdx;
944 		const deUint32	colorA	= 0xff000000 | rgb;
945 		const deUint32	colorB	= 0xff000000 | ~rgb;
946 
947 		tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec(), tcu::RGBA(colorB).toVec());
948 	}
949 
950 	// Upload.
951 	for (std::vector<TestTexture1DSp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
952 	{
953 		m_renderer.add1DTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
954 	}
955 
956 	// Compute cases.
957 	{
958 		const bool	compareModeSet		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL);
959 		const float refInRangeUpper		= compareModeSet ? 1.0f : 0.5f;
960 		const float refInRangeLower		= compareModeSet ? 0.0f : 0.5f;
961 		const float refOutOfBoundsUpper	= 1.1f;		// !< lookup function should clamp values to [0, 1] range
962 		const float refOutOfBoundsLower	= -0.1f;
963 
964 		const struct
965 		{
966 			const int	texNdx;
967 			const float	ref;
968 			const float	lodX;
969 			const float	oX;
970 		}
971 		cases[] =
972 		{
973 			{ 0,	refInRangeUpper,		+1.600f,	-1.000f	},
974 			{ 0,	refInRangeLower,		-2.000f,	-0.200f	},
975 			{ 1,	refInRangeUpper,		+0.140f,	-1.500f	},
976 			{ 1,	refInRangeLower,		-0.920f,	+0.400f	},
977 			{ 1,	refOutOfBoundsUpper,	-0.390f,	+0.650f	},
978 			{ 1,	refOutOfBoundsLower,	-1.550f,	+0.350f	},
979 		};
980 
981 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
982 		{
983 			const int	texNdx	= de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size()-1);
984 			const float ref		= cases[caseNdx].ref;
985 			const float	lodX	= cases[caseNdx].lodX;
986 			const float	oX		= cases[caseNdx].oX;
987 			const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[texNdx]->getTexture().getWidth());
988 
989 			m_cases.push_back(FilterCase(texNdx, ref, oX, oX+sX));
990 		}
991 	}
992 
993 	m_caseNdx = 0;
994 }
995 
~Texture1DShadowTestInstance(void)996 Texture1DShadowTestInstance::~Texture1DShadowTestInstance (void)
997 {
998 	m_textures.clear();
999 	m_cases.clear();
1000 }
1001 
iterate(void)1002 tcu::TestStatus Texture1DShadowTestInstance::iterate (void)
1003 {
1004 	tcu::TestLog&					log				= m_context.getTestContext().getLog();
1005 	const pipeline::TestTexture1D&	texture			= m_renderer.get1DTexture(m_cases[m_caseNdx].textureIndex);
1006 	const tcu::TextureFormat		texFmt			= texture.getTextureFormat();
1007 	const tcu::TextureFormatInfo	fmtInfo			= tcu::getTextureFormatInfo(texFmt);
1008 	const tcu::ScopedLogSection		section			(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
1009 
1010 	const FilterCase&				curCase			= m_cases[m_caseNdx];
1011 	ReferenceParams					sampleParams	(TEXTURETYPE_1D);
1012 	tcu::Surface					rendered		(m_renderer.getRenderWidth(), 1);
1013 	vector<float>					texCoord;
1014 
1015 	// Setup params for reference.
1016 	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.minFilter, m_testParameters.magFilter);
1017 	sampleParams.sampler.compare	= m_testParameters.compareOp;
1018 	sampleParams.samplerType		= SAMPLERTYPE_SHADOW;
1019 	sampleParams.lodMode			= LODMODE_EXACT;
1020 	sampleParams.colorBias			= fmtInfo.lookupBias;
1021 	sampleParams.colorScale			= fmtInfo.lookupScale;
1022 	sampleParams.ref				= curCase.ref;
1023 
1024 	log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
1025 
1026 	// Compute texture coordinates.
1027 	log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord << TestLog::EndMessage;
1028 	computeQuadTexCoord1D(texCoord, curCase.minCoord, curCase.maxCoord);
1029 
1030 	m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
1031 
1032 	{
1033 		const tcu::PixelFormat		pixelFormat			= getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1034 		tcu::LodPrecision			lodPrecision;
1035 		tcu::TexComparePrecision	texComparePrecision;
1036 
1037 		lodPrecision.derivateBits			= 18;
1038 		lodPrecision.lodBits				= 6;
1039 		texComparePrecision.coordBits		= tcu::IVec3(20,0,0);
1040 		texComparePrecision.uvwBits			= tcu::IVec3(7,0,0);
1041 		texComparePrecision.pcfBits			= 5;
1042 		texComparePrecision.referenceBits	= 16;
1043 		texComparePrecision.resultBits		= pixelFormat.redBits-1;
1044 
1045 		const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1046 														  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1047 
1048 		if (!isHighQuality)
1049 		{
1050 			m_context.getTestContext().getLog() << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
1051 
1052 			lodPrecision.lodBits			= 4;
1053 			texComparePrecision.uvwBits		= tcu::IVec3(4,0,0);
1054 			texComparePrecision.pcfBits		= 0;
1055 
1056 			const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1057 													 &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1058 
1059 			if (!isOk)
1060 			{
1061 				m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1062 				return tcu::TestStatus::fail("Image verification failed");
1063 			}
1064 		}
1065 	}
1066 
1067 	m_caseNdx += 1;
1068 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1069 }
1070 
1071 struct Texture1DArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public Texture1DArrayTestCaseParameters
1072 {
1073 };
1074 
checkTextureSupport(Context & context,const Texture1DArrayShadowTestCaseParameters & testParameters)1075 void checkTextureSupport (Context& context, const Texture1DArrayShadowTestCaseParameters& testParameters)
1076 {
1077 	const VkFormatProperties3KHR formatProperties = context.getFormatProperties(testParameters.format);
1078 	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
1079 		TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
1080 }
1081 
1082 class Texture1DArrayShadowTestInstance : public TestInstance
1083 {
1084 public:
1085 	typedef Texture1DArrayShadowTestCaseParameters	ParameterType;
1086 													Texture1DArrayShadowTestInstance		(Context& context, const ParameterType& testParameters);
1087 													~Texture1DArrayShadowTestInstance		(void);
1088 
1089 	virtual tcu::TestStatus							iterate									(void);
1090 
1091 private:
1092 													Texture1DArrayShadowTestInstance		(const Texture1DArrayShadowTestInstance& other) = delete;
1093 	Texture1DArrayShadowTestInstance&				operator=								(const Texture1DArrayShadowTestInstance& other) = delete;
1094 
1095 	struct FilterCase
1096 	{
1097 		int							textureIndex;
1098 		tcu::Vec2					minCoord;
1099 		tcu::Vec2					maxCoord;
1100 		float						ref;
1101 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture1DArrayShadowTestInstance::FilterCase1102 		FilterCase (void)
1103 			: textureIndex	(-1)
1104 			, ref			(0.0f)
1105 		{
1106 		}
1107 
FilterCasevkt::texture::__anon26fa1f1d0111::Texture1DArrayShadowTestInstance::FilterCase1108 		FilterCase (const int tex_, float ref_, const tcu::Vec2& minCoord_, const tcu::Vec2& maxCoord_)
1109 			: textureIndex	(tex_)
1110 			, minCoord		(minCoord_)
1111 			, maxCoord		(maxCoord_)
1112 			, ref			(ref_)
1113 		{
1114 		}
1115 	};
1116 
1117 	const ParameterType&				m_testParameters;
1118 	std::vector<TestTexture1DArraySp>	m_textures;
1119 	std::vector<FilterCase>				m_cases;
1120 
1121 	TextureRenderer						m_renderer;
1122 
1123 	int									m_caseNdx;
1124 };
1125 
Texture1DArrayShadowTestInstance(Context & context,const ParameterType & testParameters)1126 Texture1DArrayShadowTestInstance::Texture1DArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
1127 	: TestInstance			(context)
1128 	, m_testParameters		(testParameters)
1129 	, m_renderer			(context, testParameters.sampleCount, TEX1D_VIEWPORT_WIDTH, 1)
1130 	, m_caseNdx				(0)
1131 {
1132 	const int						numLevels	= deLog2Floor32(m_testParameters.width) + 1;
1133 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
1134 	const tcu::Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
1135 	const tcu::Vec4					cBias		= fmtInfo.valueMin;
1136 
1137 	// Create 2 textures.
1138 	m_textures.reserve(2);
1139 	for (int ndx = 0; ndx < 2; ndx++)
1140 	{
1141 		m_textures.push_back(TestTexture1DArraySp(new pipeline::TestTexture1DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.numLayers)));
1142 	}
1143 
1144 	// Fill first gradient texture.
1145 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1146 	{
1147 		const tcu::Vec4 gMin = tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
1148 		const tcu::Vec4 gMax = tcu::Vec4( 1.0f,  1.0f,  1.0f, 0.0f)*cScale + cBias;
1149 
1150 		tcu::fillWithComponentGradients(m_textures[0]->getTexture().getLevel(levelNdx), gMin, gMax);
1151 	}
1152 
1153 	// Fill second with grid texture.
1154 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1155 	{
1156 		const deUint32	step	= 0x00ffffff / numLevels;
1157 		const deUint32	rgb		= step*levelNdx;
1158 		const deUint32	colorA	= 0xff000000 | rgb;
1159 		const deUint32	colorB	= 0xff000000 | ~rgb;
1160 
1161 		tcu::fillWithGrid(m_textures[1]->getTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1162 	}
1163 
1164 	// Upload.
1165 	for (std::vector<TestTexture1DArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); ++i)
1166 	{
1167 		m_renderer.add1DArrayTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
1168 	}
1169 
1170 	// Compute cases.
1171 	{
1172 		const bool	compareModeSet		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL);
1173 		const float	refInRangeUpper		= compareModeSet ? 1.0f : 0.5f;
1174 		const float	refInRangeLower		= compareModeSet ? 0.0f : 0.5f;
1175 		const float	refOutOfBoundsUpper	= 1.1f;		// !< lookup function should clamp values to [0, 1] range
1176 		const float	refOutOfBoundsLower	= -0.1f;
1177 
1178 		const struct
1179 		{
1180 			const int	texNdx;
1181 			const float	ref;
1182 			const float	lodX;
1183 			const float	oX;
1184 		}
1185 		cases[] =
1186 		{
1187 			{ 0,	refInRangeUpper,		1.6f,	-1.0f,	},
1188 			{ 0,	refInRangeLower,		-2.0f,	-0.2f,	},
1189 			{ 1,	refInRangeUpper,		0.14f,	-1.5f,	},
1190 			{ 1,	refInRangeLower,		-0.92f,	0.4f,	},
1191 			{ 1,	refOutOfBoundsUpper,	-0.49f,	0.45f,	},
1192 			{ 1,	refOutOfBoundsLower,	-0.85f,	0.25f,	},
1193 		};
1194 
1195 		const float	minLayer	= -0.5f;
1196 		const float	maxLayer	= (float)m_testParameters.numLayers;
1197 
1198 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
1199 		{
1200 			const int	tex		= cases[caseNdx].texNdx > 0 ? 1 : 0;
1201 			const float	ref		= cases[caseNdx].ref;
1202 			const float	lodX	= cases[caseNdx].lodX;
1203 			const float	oX		= cases[caseNdx].oX;
1204 			const float	sX		= deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[tex]->getTexture().getWidth());
1205 
1206 			m_cases.push_back(FilterCase(tex, ref, tcu::Vec2(oX, minLayer), tcu::Vec2(oX+sX, maxLayer)));
1207 		}
1208 	}
1209 }
1210 
~Texture1DArrayShadowTestInstance(void)1211 Texture1DArrayShadowTestInstance::~Texture1DArrayShadowTestInstance (void)
1212 {
1213 }
1214 
iterate(void)1215 tcu::TestStatus Texture1DArrayShadowTestInstance::iterate (void)
1216 {
1217 	tcu::TestLog&						log				= m_context.getTestContext().getLog();
1218 	const FilterCase&					curCase			= m_cases[m_caseNdx];
1219 	const pipeline::TestTexture1DArray&	texture			= m_renderer.get1DArrayTexture(curCase.textureIndex);
1220 
1221 	ReferenceParams						sampleParams	(TEXTURETYPE_1D_ARRAY);
1222 	tcu::Surface						rendered		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
1223 	const tcu::ScopedLogSection			section			(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
1224 
1225 	const float							texCoord[]		=
1226 	{
1227 		curCase.minCoord.x(), curCase.minCoord.y(),
1228 		curCase.minCoord.x(), (curCase.minCoord.y() + curCase.maxCoord.y()) / 2.0f,
1229 		curCase.maxCoord.x(), (curCase.minCoord.y() + curCase.maxCoord.y()) / 2.0f,
1230 		curCase.maxCoord.x(), curCase.maxCoord.y()
1231 	};
1232 
1233 	// Setup params for reference.
1234 	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.minFilter, m_testParameters.magFilter);
1235 	sampleParams.sampler.compare	= m_testParameters.compareOp;
1236 	sampleParams.samplerType		= SAMPLERTYPE_SHADOW;
1237 	sampleParams.lodMode			= LODMODE_EXACT;
1238 	sampleParams.ref				= curCase.ref;
1239 
1240 	log	<< TestLog::Message
1241 		<< "Compare reference value = " << sampleParams.ref << "\n"
1242 		<< "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
1243 		<< TestLog::EndMessage;
1244 
1245 	m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], sampleParams);
1246 
1247 	{
1248 		const tcu::PixelFormat		pixelFormat			= getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1249 		tcu::LodPrecision			lodPrecision;
1250 		tcu::TexComparePrecision	texComparePrecision;
1251 
1252 		lodPrecision.derivateBits			= 18;
1253 		lodPrecision.lodBits				= 6;
1254 		texComparePrecision.coordBits		= tcu::IVec3(20,20,20);
1255 		texComparePrecision.uvwBits			= tcu::IVec3(7,7,7);
1256 		texComparePrecision.pcfBits			= 5;
1257 		texComparePrecision.referenceBits	= 16;
1258 		texComparePrecision.resultBits		= pixelFormat.redBits-1;
1259 
1260 		const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1261 														  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1262 
1263 		if (!isHighQuality)
1264 		{
1265 			log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
1266 
1267 			lodPrecision.lodBits			= 4;
1268 			texComparePrecision.uvwBits		= tcu::IVec3(4,4,4);
1269 			texComparePrecision.pcfBits		= 0;
1270 
1271 			const bool isOk = verifyTexCompareResult(m_context.getTestContext(), rendered.getAccess(), texture.getTexture(),
1272 													 &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1273 
1274 			if (!isOk)
1275 			{
1276 				log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1277 				return tcu::TestStatus::fail("Image verification failed");
1278 			}
1279 		}
1280 	}
1281 
1282 	m_caseNdx += 1;
1283 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1284 }
1285 
1286 struct TextureCubeArrayShadowTestCaseParameters : public TextureShadowCommonTestCaseParameters, public TextureCubeArrayTestCaseParameters
1287 {
1288 };
1289 
checkTextureSupport(Context & context,const TextureCubeArrayShadowTestCaseParameters & testParameters)1290 void checkTextureSupport (Context& context, const TextureCubeArrayShadowTestCaseParameters& testParameters)
1291 {
1292 	const VkFormatProperties3KHR formatProperties = context.getFormatProperties(testParameters.format);
1293 	if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR))
1294 		TCU_THROW(NotSupportedError, "Format does not support shadow sampling");
1295 }
1296 
1297 class TextureCubeArrayShadowTestInstance : public TestInstance
1298 {
1299 public:
1300 	typedef TextureCubeArrayShadowTestCaseParameters	ParameterType;
1301 														TextureCubeArrayShadowTestInstance	(Context& context, const ParameterType& testParameters);
1302 														~TextureCubeArrayShadowTestInstance	(void);
1303 
1304 	virtual tcu::TestStatus								iterate								(void);
1305 
1306 private:
1307 														TextureCubeArrayShadowTestInstance	(const TextureCubeArrayShadowTestInstance& other);
1308 	TextureCubeArrayShadowTestInstance&					operator=							(const TextureCubeArrayShadowTestInstance& other);
1309 
1310 	struct FilterCase
1311 	{
1312 		int						textureIndex;
1313 		tcu::Vec2				bottomLeft;
1314 		tcu::Vec2				topRight;
1315 		float					ref;
1316 
FilterCasevkt::texture::__anon26fa1f1d0111::TextureCubeArrayShadowTestInstance::FilterCase1317 		FilterCase (void)
1318 			: textureIndex	(-1)
1319 			, ref			(0.0f)
1320 		{
1321 		}
1322 
FilterCasevkt::texture::__anon26fa1f1d0111::TextureCubeArrayShadowTestInstance::FilterCase1323 		FilterCase (const int tex_, const float ref_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_)
1324 			: textureIndex	(tex_)
1325 			, bottomLeft	(bottomLeft_)
1326 			, topRight		(topRight_)
1327 			, ref			(ref_)
1328 		{
1329 		}
1330 	};
1331 
1332 	const ParameterType&			m_testParameters;
1333 	vector<TestTextureCubeArraySp>	m_textures;
1334 	std::vector<FilterCase>			m_cases;
1335 
1336 	TextureRenderer					m_renderer;
1337 	int								m_caseNdx;
1338 };
1339 
TextureCubeArrayShadowTestInstance(Context & context,const ParameterType & testParameters)1340 TextureCubeArrayShadowTestInstance::TextureCubeArrayShadowTestInstance (Context& context, const ParameterType& testParameters)
1341 	: TestInstance			(context)
1342 	, m_testParameters		(testParameters)
1343 	, m_renderer			(context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
1344 	, m_caseNdx				(0)
1345 {
1346 	const int						numLevels	= deLog2Floor32(m_testParameters.size)+1;
1347 	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(vk::mapVkFormat(m_testParameters.format));
1348 	const tcu::Vec4					cBias		= fmtInfo.valueMin;
1349 	const tcu::Vec4					cScale		= fmtInfo.valueMax-fmtInfo.valueMin;
1350 
1351 	// Create textures.
1352 
1353 	m_textures.reserve(2);
1354 	for (int ndx = 0; ndx < 2; ndx++)
1355 	{
1356 		m_textures.push_back(TestTextureCubeArraySp(new pipeline::TestTextureCubeArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.size, m_testParameters.numLayers)));
1357 	}
1358 
1359 	// Fill first with gradient texture.
1360 	static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
1361 	{
1362 		{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
1363 		{ tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
1364 		{ tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
1365 		{ tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
1366 		{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
1367 		{ tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
1368 	};
1369 
1370 	for (int layerFace = 0; layerFace < m_textures[0]->getArraySize(); layerFace++)
1371 	{
1372 		const int		face		= layerFace % 6;
1373 		const int		layer		= layerFace / 6;
1374 		const tcu::Vec4	gradient0	= gradients[face][0] / float(layer + 1);
1375 		const tcu::Vec4	gradient1	= gradients[face][1] / float(layer + 1);
1376 
1377 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1378 		{
1379 			tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, layerFace), gradient0*cScale + cBias, gradient1*cScale + cBias);
1380 		}
1381 	}
1382 
1383 	// Fill second with grid texture.
1384 	for (int layerFace = 0; layerFace < m_textures[1]->getArraySize(); layerFace++)
1385 	{
1386 		const int	face		= layerFace % 6;
1387 		const int	layer		= layerFace / 6;
1388 		const int	cellSize	= 4 + layer;
1389 
1390 		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1391 		{
1392 			const deUint32	step	= 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
1393 			const deUint32	rgb		= step*levelNdx*face;
1394 			const deUint32	colorA	= 0xff000000 | rgb;
1395 			const deUint32	colorB	= 0xff000000 | ~rgb;
1396 
1397 			tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, layerFace), cellSize, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1398 		}
1399 	}
1400 
1401 	// Upload.
1402 	for (vector<TestTextureCubeArraySp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
1403 	{
1404 		m_renderer.addCubeArrayTexture(*i, m_testParameters.aspectMask, m_testParameters.backingMode);
1405 	}
1406 
1407 	// Compute cases
1408 	{
1409 		const bool	compareModeSet		= (m_testParameters.compareOp == Sampler::COMPAREMODE_EQUAL || m_testParameters.compareOp == Sampler::COMPAREMODE_NOT_EQUAL);
1410 		const float refInRangeUpper		= compareModeSet ? 1.0f : 0.5f;
1411 		const float refInRangeLower		= compareModeSet ? 0.0f : 0.5f;
1412 		const float refOutOfBoundsUpper	= 1.1f;
1413 		const float refOutOfBoundsLower	= -0.1f;
1414 
1415 		m_cases.push_back(FilterCase(0,	refInRangeUpper,		tcu::Vec2(-1.25f, -1.2f),	tcu::Vec2(1.2f, 1.25f)));	// minification
1416 		m_cases.push_back(FilterCase(0,	refInRangeLower,		tcu::Vec2(0.8f, 0.8f),		tcu::Vec2(1.25f, 1.20f)));	// magnification
1417 		m_cases.push_back(FilterCase(1,	refInRangeUpper,		tcu::Vec2(-1.19f, -1.3f),	tcu::Vec2(1.1f, 1.35f)));	// minification
1418 		m_cases.push_back(FilterCase(1,	refInRangeLower,		tcu::Vec2(-1.2f, -1.1f),	tcu::Vec2(-0.8f, -0.8f)));	// magnification
1419 		m_cases.push_back(FilterCase(1,	refOutOfBoundsUpper,	tcu::Vec2(-0.61f, -0.1f),	tcu::Vec2(0.9f, 1.18f)));	// reference value clamp, upper
1420 		m_cases.push_back(FilterCase(1,	refOutOfBoundsLower,	tcu::Vec2(-0.75f, 1.0f),	tcu::Vec2(0.05f, 0.75f)));	// reference value clamp, lower
1421 	}
1422 }
1423 
~TextureCubeArrayShadowTestInstance(void)1424 TextureCubeArrayShadowTestInstance::~TextureCubeArrayShadowTestInstance	(void)
1425 {
1426 }
1427 
iterate(void)1428 tcu::TestStatus TextureCubeArrayShadowTestInstance::iterate (void)
1429 {
1430 
1431 	tcu::TestLog&							log				= m_context.getTestContext().getLog();
1432 	const tcu::ScopedLogSection				iterSection		(log, string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
1433 	const FilterCase&						curCase			= m_cases[m_caseNdx];
1434 	const pipeline::TestTextureCubeArray&	texture			= m_renderer.getCubeArrayTexture(curCase.textureIndex);
1435 
1436 	ReferenceParams							sampleParams	(TEXTURETYPE_CUBE_ARRAY);
1437 
1438 	// Params for reference computation.
1439 	sampleParams.sampler					= util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter, m_testParameters.magFilter);
1440 	sampleParams.sampler.seamlessCubeMap	= true;
1441 	sampleParams.sampler.compare			= m_testParameters.compareOp;
1442 	sampleParams.samplerType				= SAMPLERTYPE_SHADOW;
1443 	sampleParams.lodMode					= LODMODE_EXACT;
1444 	sampleParams.ref						= curCase.ref;
1445 
1446 	log	<< TestLog::Message
1447 		<< "Compare reference value = " << sampleParams.ref << "\n"
1448 		<< "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
1449 		<< TestLog::EndMessage;
1450 
1451 	for (int layerFace = 0; layerFace < m_textures[curCase.textureIndex]->getArraySize(); layerFace++)
1452 	{
1453 		const tcu::CubeFace		face		= tcu::CubeFace(layerFace % 6);
1454 		const int				layer		= layerFace / 6;
1455 		const float				minLayer	= -0.5f + float(layer);
1456 		const float				maxLayer	= (float)m_testParameters.numLayers;
1457 		tcu::Surface			result		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
1458 		vector<float>			texCoord;
1459 
1460 		computeQuadTexCoordCubeArray(texCoord, face, curCase.bottomLeft, curCase.topRight, tcu::Vec2(minLayer, maxLayer));
1461 
1462 		log << TestLog::Message << "Face " << getFaceDesc(face) << " at layer " << layer << TestLog::EndMessage;
1463 
1464 		// \todo Log texture coordinates.
1465 
1466 		m_renderer.renderQuad(result, curCase.textureIndex, &texCoord[0], sampleParams);
1467 
1468 		{
1469 			const tcu::PixelFormat		pixelFormat			= getPixelFormat(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1470 			tcu::LodPrecision			lodPrecision;
1471 			tcu::TexComparePrecision	texComparePrecision;
1472 
1473 			lodPrecision.derivateBits			= 10;
1474 			lodPrecision.lodBits				= 5;
1475 			texComparePrecision.coordBits		= tcu::IVec3(10,10,10);
1476 			texComparePrecision.uvwBits			= tcu::IVec3(6,6,0);
1477 			texComparePrecision.pcfBits			= 5;
1478 			texComparePrecision.referenceBits	= 16;
1479 			texComparePrecision.resultBits		= pixelFormat.redBits-1;
1480 
1481 			const bool isHighQuality = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
1482 															  &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1483 
1484 			if (!isHighQuality)
1485 			{
1486 				log << TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << TestLog::EndMessage;
1487 
1488 				lodPrecision.lodBits			= 4;
1489 				texComparePrecision.uvwBits		= tcu::IVec3(4,4,0);
1490 				texComparePrecision.pcfBits		= 0;
1491 
1492 				const bool isOk = verifyTexCompareResult(m_context.getTestContext(), result.getAccess(), texture.getTexture(),
1493 														 &texCoord[0], sampleParams, texComparePrecision, lodPrecision, pixelFormat);
1494 
1495 				if (!isOk)
1496 				{
1497 					log << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
1498 					return tcu::TestStatus::fail("Image verification failed");
1499 				}
1500 			}
1501 		}
1502 	}
1503 
1504 	m_caseNdx += 1;
1505 	return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1506 }
1507 } // anonymous
1508 
populateTextureShadowTests(tcu::TestCaseGroup * textureShadowTests)1509 void populateTextureShadowTests (tcu::TestCaseGroup* textureShadowTests)
1510 {
1511 	tcu::TestContext&				testCtx				= textureShadowTests->getTestContext();
1512 
1513 	static const struct
1514 	{
1515 		const char*								name;
1516 		const TextureBinding::ImageBackingMode	backingMode;
1517 	} backingModes[] =
1518 	{
1519 		{ "",			TextureBinding::IMAGE_BACKING_MODE_REGULAR	},
1520 		{ "sparse_",	TextureBinding::IMAGE_BACKING_MODE_SPARSE	}
1521 	};
1522 
1523 	static const struct
1524 	{
1525 		const char*								name;
1526 		const VkFormat							format;
1527 		const VkImageAspectFlags				aspect;
1528 	} formats[] =
1529 	{
1530 		{ "d16_unorm",				VK_FORMAT_D16_UNORM,			VK_IMAGE_ASPECT_DEPTH_BIT	},
1531 		{ "x8_d24_unorm_pack32",	VK_FORMAT_X8_D24_UNORM_PACK32,	VK_IMAGE_ASPECT_DEPTH_BIT	},
1532 		{ "d32_sfloat",				VK_FORMAT_D32_SFLOAT,			VK_IMAGE_ASPECT_DEPTH_BIT	},
1533 		{ "d16_unorm_s8_uint",		VK_FORMAT_D16_UNORM_S8_UINT,	VK_IMAGE_ASPECT_DEPTH_BIT	},
1534 		{ "d24_unorm_s8_uint",		VK_FORMAT_D24_UNORM_S8_UINT,	VK_IMAGE_ASPECT_DEPTH_BIT	},
1535 		{ "d32_sfloat_s8_uint",		VK_FORMAT_D32_SFLOAT_S8_UINT,	VK_IMAGE_ASPECT_DEPTH_BIT	},
1536 		{ "r16_unorm",				VK_FORMAT_R16_UNORM,			VK_IMAGE_ASPECT_COLOR_BIT	},
1537 		{ "r32_sfloat",				VK_FORMAT_R32_SFLOAT,			VK_IMAGE_ASPECT_COLOR_BIT	}
1538 	};
1539 
1540 	static const struct
1541 	{
1542 		const char*								name;
1543 		const Sampler::FilterMode				minFilter;
1544 		const Sampler::FilterMode				magFilter;
1545 	} filters[] =
1546 	{
1547 		{ "nearest",				Sampler::NEAREST,					Sampler::NEAREST	},
1548 		{ "linear",					Sampler::LINEAR,					Sampler::LINEAR		},
1549 		{ "nearest_mipmap_nearest",	Sampler::NEAREST_MIPMAP_NEAREST,	Sampler::LINEAR		},
1550 		{ "linear_mipmap_nearest",	Sampler::LINEAR_MIPMAP_NEAREST,		Sampler::LINEAR		},
1551 		{ "nearest_mipmap_linear",	Sampler::NEAREST_MIPMAP_LINEAR,		Sampler::LINEAR		},
1552 		{ "linear_mipmap_linear",	Sampler::LINEAR_MIPMAP_LINEAR,		Sampler::LINEAR		}
1553 	};
1554 
1555 	static const struct
1556 	{
1557 		const char*								name;
1558 		const Sampler::CompareMode				op;
1559 	} compareOp[] =
1560 	{
1561 		{ "less_or_equal",		Sampler::COMPAREMODE_LESS_OR_EQUAL		},
1562 		{ "greater_or_equal",	Sampler::COMPAREMODE_GREATER_OR_EQUAL	},
1563 		{ "less",				Sampler::COMPAREMODE_LESS				},
1564 		{ "greater",			Sampler::COMPAREMODE_GREATER			},
1565 		{ "equal",				Sampler::COMPAREMODE_EQUAL				},
1566 		{ "not_equal",			Sampler::COMPAREMODE_NOT_EQUAL			},
1567 		{ "always",				Sampler::COMPAREMODE_ALWAYS				},
1568 		{ "never",				Sampler::COMPAREMODE_NEVER				}
1569 	};
1570 
1571 	// 2D cases.
1572 	{
1573 		de::MovePtr<tcu::TestCaseGroup>	group2D	(new tcu::TestCaseGroup(testCtx, "2d", "2D texture shadow lookup tests"));
1574 
1575 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1576 		{
1577 			de::MovePtr<tcu::TestCaseGroup>	filterGroup	(new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1578 
1579 			for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1580 			{
1581 				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1582 				{
1583 					for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1584 					{
1585 						const string						name	= string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1586 						Texture2DShadowTestCaseParameters	testParameters;
1587 
1588 						testParameters.minFilter	= filters[filterNdx].minFilter;
1589 						testParameters.magFilter	= filters[filterNdx].magFilter;
1590 						testParameters.format		= formats[formatNdx].format;
1591 						testParameters.backingMode	= backingModes[backingNdx].backingMode;
1592 						testParameters.compareOp	= compareOp[compareNdx].op;
1593 						testParameters.wrapS		= Sampler::REPEAT_GL;
1594 						testParameters.wrapT		= Sampler::REPEAT_GL;
1595 						testParameters.width		= 32;
1596 						testParameters.height		= 64;
1597 						testParameters.aspectMask	= formats[formatNdx].aspect;
1598 						testParameters.programs.push_back(PROGRAM_2D_SHADOW);
1599 
1600 						filterGroup->addChild(new TextureTestCase<Texture2DShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1601 					}
1602 				}
1603 			}
1604 
1605 			group2D->addChild(filterGroup.release());
1606 		}
1607 
1608 		textureShadowTests->addChild(group2D.release());
1609 	}
1610 
1611 	// Cubemap cases.
1612 	{
1613 		de::MovePtr<tcu::TestCaseGroup>	groupCube	(new tcu::TestCaseGroup(testCtx, "cube", "Cube map texture shadow lookup tests"));
1614 
1615 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1616 		{
1617 			de::MovePtr<tcu::TestCaseGroup>	filterGroup	(new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1618 
1619 			for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1620 			{
1621 				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1622 				{
1623 					for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1624 					{
1625 						const string							name	= string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1626 						TextureCubeShadowTestCaseParameters		testParameters;
1627 
1628 						testParameters.minFilter	= filters[filterNdx].minFilter;
1629 						testParameters.magFilter	= filters[filterNdx].magFilter;
1630 						testParameters.format		= formats[formatNdx].format;
1631 						testParameters.backingMode	= backingModes[backingNdx].backingMode;
1632 						testParameters.compareOp	= compareOp[compareNdx].op;
1633 						testParameters.wrapS		= Sampler::REPEAT_GL;
1634 						testParameters.wrapT		= Sampler::REPEAT_GL;
1635 						testParameters.size			= 32;
1636 						testParameters.aspectMask	= formats[formatNdx].aspect;
1637 
1638 						testParameters.programs.push_back(PROGRAM_CUBE_SHADOW);
1639 
1640 						filterGroup->addChild(new TextureTestCase<TextureCubeShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1641 					}
1642 				}
1643 			}
1644 
1645 			groupCube->addChild(filterGroup.release());
1646 		}
1647 
1648 		textureShadowTests->addChild(groupCube.release());
1649 	}
1650 
1651 	// 2D array cases.
1652 	{
1653 		de::MovePtr<tcu::TestCaseGroup>	group2DArray	(new tcu::TestCaseGroup(testCtx, "2d_array", "2D texture array shadow lookup tests"));
1654 
1655 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1656 		{
1657 			de::MovePtr<tcu::TestCaseGroup>	filterGroup	(new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1658 
1659 			for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1660 			{
1661 				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1662 				{
1663 					for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1664 					{
1665 						const string							name	= string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1666 						Texture2DArrayShadowTestCaseParameters	testParameters;
1667 
1668 						testParameters.minFilter	= filters[filterNdx].minFilter;
1669 						testParameters.magFilter	= filters[filterNdx].magFilter;
1670 						testParameters.format		= formats[formatNdx].format;
1671 						testParameters.backingMode	= backingModes[backingNdx].backingMode;
1672 						testParameters.compareOp	= compareOp[compareNdx].op;
1673 						testParameters.wrapS		= Sampler::REPEAT_GL;
1674 						testParameters.wrapT		= Sampler::REPEAT_GL;
1675 						testParameters.width		= 32;
1676 						testParameters.height		= 64;
1677 						testParameters.numLayers	= 8;
1678 						testParameters.aspectMask	= formats[formatNdx].aspect;
1679 
1680 						testParameters.programs.push_back(PROGRAM_2D_ARRAY_SHADOW);
1681 
1682 						filterGroup->addChild(new TextureTestCase<Texture2DArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1683 					}
1684 				}
1685 			}
1686 
1687 			group2DArray->addChild(filterGroup.release());
1688 		}
1689 
1690 		textureShadowTests->addChild(group2DArray.release());
1691 	}
1692 
1693 	// 1D cases.
1694 	{
1695 		de::MovePtr<tcu::TestCaseGroup>	group1D	(new tcu::TestCaseGroup(testCtx, "1d", "1D texture shadow lookup tests"));
1696 
1697 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1698 		{
1699 			de::MovePtr<tcu::TestCaseGroup>	filterGroup	(new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1700 
1701 			for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1702 			{
1703 				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1704 				{
1705 					for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1706 					{
1707 						const string						name			= string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1708 						Texture1DShadowTestCaseParameters	testParameters;
1709 
1710 						testParameters.minFilter	= filters[filterNdx].minFilter;
1711 						testParameters.magFilter	= filters[filterNdx].magFilter;
1712 						testParameters.format		= formats[formatNdx].format;
1713 						testParameters.backingMode	= backingModes[backingNdx].backingMode;
1714 						testParameters.compareOp	= compareOp[compareNdx].op;
1715 						testParameters.wrapS		= Sampler::REPEAT_GL;
1716 						testParameters.width		= 32;
1717 						testParameters.aspectMask	= formats[formatNdx].aspect;
1718 						testParameters.programs.push_back(PROGRAM_1D_SHADOW);
1719 
1720 						filterGroup->addChild(new TextureTestCase<Texture1DShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1721 					}
1722 				}
1723 			}
1724 
1725 			group1D->addChild(filterGroup.release());
1726 		}
1727 
1728 		textureShadowTests->addChild(group1D.release());
1729 	}
1730 
1731 	// 1D array cases.
1732 	{
1733 		de::MovePtr<tcu::TestCaseGroup>	group1DArray	(new tcu::TestCaseGroup(testCtx, "1d_array", "1D texture array shadow lookup tests"));
1734 
1735 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1736 		{
1737 			de::MovePtr<tcu::TestCaseGroup>	filterGroup	(new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1738 
1739 			for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1740 			{
1741 				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1742 				{
1743 					for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1744 					{
1745 						const string							name			= string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1746 						Texture1DArrayShadowTestCaseParameters	testParameters;
1747 
1748 						testParameters.minFilter	= filters[filterNdx].minFilter;
1749 						testParameters.magFilter	= filters[filterNdx].magFilter;
1750 						testParameters.format		= formats[formatNdx].format;
1751 						testParameters.backingMode	= backingModes[backingNdx].backingMode;
1752 						testParameters.compareOp	= compareOp[compareNdx].op;
1753 						testParameters.wrapS		= Sampler::REPEAT_GL;
1754 						testParameters.width		= 32;
1755 						testParameters.numLayers	= 8;
1756 						testParameters.aspectMask	= formats[formatNdx].aspect;
1757 
1758 						testParameters.programs.push_back(PROGRAM_1D_ARRAY_SHADOW);
1759 
1760 						filterGroup->addChild(new TextureTestCase<Texture1DArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1761 					}
1762 				}
1763 			}
1764 
1765 			group1DArray->addChild(filterGroup.release());
1766 		}
1767 
1768 		textureShadowTests->addChild(group1DArray.release());
1769 	}
1770 
1771 	// Cubemap Array cases.
1772 	{
1773 		de::MovePtr<tcu::TestCaseGroup>	groupCubeArray	(new tcu::TestCaseGroup(testCtx, "cube_array", "Cube map texture shadow lookup tests"));
1774 
1775 		for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(filters); filterNdx++)
1776 		{
1777 			de::MovePtr<tcu::TestCaseGroup>	filterGroup	(new tcu::TestCaseGroup(testCtx, filters[filterNdx].name, ""));
1778 
1779 			for (int compareNdx = 0; compareNdx < DE_LENGTH_OF_ARRAY(compareOp); compareNdx++)
1780 			{
1781 				for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
1782 				{
1783 					for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
1784 					{
1785 						const string								name			= string(backingModes[backingNdx].name) + compareOp[compareNdx].name + "_" + formats[formatNdx].name;
1786 						TextureCubeArrayShadowTestCaseParameters	testParameters;
1787 
1788 						testParameters.minFilter	= filters[filterNdx].minFilter;
1789 						testParameters.magFilter	= filters[filterNdx].magFilter;
1790 						testParameters.format		= formats[formatNdx].format;
1791 						testParameters.backingMode	= backingModes[backingNdx].backingMode;
1792 						testParameters.compareOp	= compareOp[compareNdx].op;
1793 						testParameters.wrapS		= Sampler::REPEAT_GL;
1794 						testParameters.wrapT		= Sampler::REPEAT_GL;
1795 						testParameters.size			= 32;
1796 						testParameters.numLayers	= 4 * 6;
1797 						testParameters.aspectMask	= formats[formatNdx].aspect;
1798 
1799 						testParameters.programs.push_back(PROGRAM_CUBE_ARRAY_SHADOW);
1800 
1801 						filterGroup->addChild(new TextureTestCase<TextureCubeArrayShadowTestInstance>(testCtx, name.c_str(), "", testParameters));
1802 					}
1803 				}
1804 			}
1805 
1806 			groupCubeArray->addChild(filterGroup.release());
1807 		}
1808 
1809 		textureShadowTests->addChild(groupCubeArray.release());
1810 	}
1811 
1812 }
1813 
createTextureShadowTests(tcu::TestContext & testCtx)1814 tcu::TestCaseGroup* createTextureShadowTests (tcu::TestContext& testCtx)
1815 {
1816 	return createTestGroup(testCtx, "shadow", "Texture shadow tests.", populateTextureShadowTests);
1817 }
1818 
1819 } // texture
1820 } // vkt
1821