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