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