1/*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Compressed texture tests.
24 *//*--------------------------------------------------------------------*/
25
26#include "vktTextureCompressedFormatTests.hpp"
27
28#include "deString.h"
29#include "deStringUtil.hpp"
30#include "tcuCompressedTexture.hpp"
31#include "tcuImageCompare.hpp"
32#include "tcuTexture.hpp"
33#include "tcuTextureUtil.hpp"
34#include "tcuVectorUtil.hpp"
35#include "tcuAstcUtil.hpp"
36#include "vkImageUtil.hpp"
37#include "vktTestGroupUtil.hpp"
38#include "vktTextureTestUtil.hpp"
39#include <string>
40#include <vector>
41
42namespace vkt
43{
44namespace texture
45{
46namespace
47{
48
49using namespace vk;
50using namespace glu::TextureTestUtil;
51using namespace texture::util;
52
53using std::string;
54using std::vector;
55using tcu::Sampler;
56using tcu::TestLog;
57
58// Compressed formats
59static const struct {
60	const VkFormat	format;
61} formats[] =
62{
63	{ VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK		},
64	{ VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK		},
65	{ VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK	},
66	{ VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK	},
67	{ VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK	},
68	{ VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK	},
69
70	{ VK_FORMAT_EAC_R11_UNORM_BLOCK			},
71	{ VK_FORMAT_EAC_R11_SNORM_BLOCK			},
72	{ VK_FORMAT_EAC_R11G11_UNORM_BLOCK		},
73	{ VK_FORMAT_EAC_R11G11_SNORM_BLOCK		},
74
75	{ VK_FORMAT_ASTC_4x4_UNORM_BLOCK		},
76	{ VK_FORMAT_ASTC_4x4_SRGB_BLOCK			},
77	{ VK_FORMAT_ASTC_5x4_UNORM_BLOCK		},
78	{ VK_FORMAT_ASTC_5x4_SRGB_BLOCK			},
79	{ VK_FORMAT_ASTC_5x5_UNORM_BLOCK		},
80	{ VK_FORMAT_ASTC_5x5_SRGB_BLOCK			},
81	{ VK_FORMAT_ASTC_6x5_UNORM_BLOCK		},
82	{ VK_FORMAT_ASTC_6x5_SRGB_BLOCK			},
83	{ VK_FORMAT_ASTC_6x6_UNORM_BLOCK		},
84	{ VK_FORMAT_ASTC_6x6_SRGB_BLOCK			},
85	{ VK_FORMAT_ASTC_8x5_UNORM_BLOCK		},
86	{ VK_FORMAT_ASTC_8x5_SRGB_BLOCK			},
87	{ VK_FORMAT_ASTC_8x6_UNORM_BLOCK		},
88	{ VK_FORMAT_ASTC_8x6_SRGB_BLOCK			},
89	{ VK_FORMAT_ASTC_8x8_UNORM_BLOCK		},
90	{ VK_FORMAT_ASTC_8x8_SRGB_BLOCK			},
91	{ VK_FORMAT_ASTC_10x5_UNORM_BLOCK		},
92	{ VK_FORMAT_ASTC_10x5_SRGB_BLOCK		},
93	{ VK_FORMAT_ASTC_10x6_UNORM_BLOCK		},
94	{ VK_FORMAT_ASTC_10x6_SRGB_BLOCK		},
95	{ VK_FORMAT_ASTC_10x8_UNORM_BLOCK		},
96	{ VK_FORMAT_ASTC_10x8_SRGB_BLOCK		},
97	{ VK_FORMAT_ASTC_10x10_UNORM_BLOCK		},
98	{ VK_FORMAT_ASTC_10x10_SRGB_BLOCK		},
99	{ VK_FORMAT_ASTC_12x10_UNORM_BLOCK		},
100	{ VK_FORMAT_ASTC_12x10_SRGB_BLOCK		},
101	{ VK_FORMAT_ASTC_12x12_UNORM_BLOCK		},
102	{ VK_FORMAT_ASTC_12x12_SRGB_BLOCK		},
103
104	{ VK_FORMAT_BC1_RGB_UNORM_BLOCK			},
105	{ VK_FORMAT_BC1_RGB_SRGB_BLOCK			},
106	{ VK_FORMAT_BC1_RGBA_UNORM_BLOCK		},
107	{ VK_FORMAT_BC1_RGBA_SRGB_BLOCK			},
108	{ VK_FORMAT_BC2_UNORM_BLOCK				},
109	{ VK_FORMAT_BC2_SRGB_BLOCK				},
110	{ VK_FORMAT_BC3_UNORM_BLOCK				},
111	{ VK_FORMAT_BC3_SRGB_BLOCK				},
112	{ VK_FORMAT_BC4_UNORM_BLOCK				},
113	{ VK_FORMAT_BC4_SNORM_BLOCK				},
114	{ VK_FORMAT_BC5_UNORM_BLOCK				},
115	{ VK_FORMAT_BC5_SNORM_BLOCK				},
116	{ VK_FORMAT_BC6H_UFLOAT_BLOCK			},
117	{ VK_FORMAT_BC6H_SFLOAT_BLOCK			},
118	{ VK_FORMAT_BC7_UNORM_BLOCK				},
119	{ VK_FORMAT_BC7_SRGB_BLOCK				}
120};
121
122static const struct {
123	const int	width;
124	const int	height;
125	const int	depth;		// 2D test ignore depth value
126	const bool	mipmaps;
127	const char*	name;
128} sizes[] =
129{
130	{ 128, 64, 8,  false, "pot"  },
131	{ 51,  65, 17, false, "npot" },
132	{ 51,  65, 17, true,  "npot_mip1" },
133};
134
135static const struct {
136	const char*								name;
137	const TextureBinding::ImageBackingMode	backingMode;
138} backingModes[] =
139{
140	{ "",			TextureBinding::IMAGE_BACKING_MODE_REGULAR	},
141#ifndef CTS_USES_VULKANSC
142	{ "_sparse",	TextureBinding::IMAGE_BACKING_MODE_SPARSE	}
143#endif // CTS_USES_VULKANSC
144};
145
146struct Compressed3DTestParameters : public Texture3DTestCaseParameters
147{
148										Compressed3DTestParameters	(void);
149	TextureBinding::ImageBackingMode	backingMode;
150};
151
152Compressed3DTestParameters::Compressed3DTestParameters (void)
153	: backingMode(TextureBinding::IMAGE_BACKING_MODE_REGULAR)
154{
155}
156
157struct Compressed2DTestParameters : public Texture2DTestCaseParameters
158{
159										Compressed2DTestParameters	(void);
160	TextureBinding::ImageBackingMode	backingMode;
161};
162
163Compressed2DTestParameters::Compressed2DTestParameters (void)
164	: backingMode(TextureBinding::IMAGE_BACKING_MODE_REGULAR)
165{
166}
167
168class Compressed2DTestInstance : public TestInstance
169{
170public:
171	typedef Compressed2DTestParameters	ParameterType;
172
173										Compressed2DTestInstance	(Context&				context,
174																	 const ParameterType&	testParameters);
175	tcu::TestStatus						iterate						(void);
176
177private:
178										Compressed2DTestInstance	(const Compressed2DTestInstance& other);
179	Compressed2DTestInstance&			operator=					(const Compressed2DTestInstance& other);
180
181	const ParameterType&				m_testParameters;
182	const tcu::CompressedTexFormat		m_compressedFormat;
183	TestTexture2DSp						m_texture;
184	TextureRenderer						m_renderer;
185};
186
187Compressed2DTestInstance::Compressed2DTestInstance (Context&				context,
188													const ParameterType&	testParameters)
189	: TestInstance			(context)
190	, m_testParameters		(testParameters)
191	, m_compressedFormat	(mapVkCompressedFormat(testParameters.format))
192	, m_texture				(TestTexture2DSp(new pipeline::TestTexture2D(m_compressedFormat, testParameters.width, testParameters.height)))
193	, m_renderer			(context, testParameters.sampleCount, testParameters.width, testParameters.height)
194{
195	m_renderer.add2DTexture(m_texture, testParameters.aspectMask, testParameters.backingMode);
196}
197
198static void computeScaleAndBias (const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, tcu::Vec4& scale, tcu::Vec4& bias)
199{
200	tcu::Vec4 minVal;
201	tcu::Vec4 maxVal;
202	const float eps = 0.0001f;
203
204	{
205		tcu::Vec4 refMin;
206		tcu::Vec4 refMax;
207		estimatePixelValueRange(reference, refMin, refMax);
208
209		minVal	= refMin;
210		maxVal	= refMax;
211	}
212
213	{
214		tcu::Vec4 resMin;
215		tcu::Vec4 resMax;
216
217		estimatePixelValueRange(result, resMin, resMax);
218
219		minVal[0] = de::min(minVal[0], resMin[0]);
220		minVal[1] = de::min(minVal[1], resMin[1]);
221		minVal[2] = de::min(minVal[2], resMin[2]);
222		minVal[3] = de::min(minVal[3], resMin[3]);
223
224		maxVal[0] = de::max(maxVal[0], resMax[0]);
225		maxVal[1] = de::max(maxVal[1], resMax[1]);
226		maxVal[2] = de::max(maxVal[2], resMax[2]);
227		maxVal[3] = de::max(maxVal[3], resMax[3]);
228	}
229
230	for (int c = 0; c < 4; c++)
231	{
232		if (maxVal[c] - minVal[c] < eps)
233		{
234			scale[c]	= (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]);
235			bias[c]		= (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]);
236		}
237		else
238		{
239			scale[c]	= 1.0f / (maxVal[c] - minVal[c]);
240			bias[c]		= 0.0f - minVal[c]*scale[c];
241		}
242	}
243}
244
245static inline tcu::UVec4 min (tcu::UVec4 a, tcu::UVec4 b)
246{
247	return tcu::UVec4(	deMin32(a[0], b[0]),
248						deMin32(a[1], b[1]),
249						deMin32(a[2], b[2]),
250						deMin32(a[3], b[3]));
251}
252
253static bool compareColor (tcu::RGBA reference, tcu::RGBA result, tcu::RGBA threshold, tcu::UVec4& diff)
254{
255	const tcu::IVec4 refPix			= reference.toIVec();
256	const tcu::IVec4 cmpPix			= result.toIVec();
257	const tcu::UVec4 thresholdVec	= threshold.toIVec().cast<deUint32>();
258	diff							= abs(refPix - cmpPix).cast<deUint32>();
259
260	return boolAll(lessThanEqual(diff, thresholdVec));
261}
262
263template <typename TextureType>
264static bool validateTexture (tcu::TestLog& log, const tcu::Surface& rendered, const TextureType& texture, const vector<float> &texCoord, deUint32 mipLevel,
265		const tcu::PixelFormat &pixelFormat, const tcu::RGBA& colorThreshold, float coordThreshold, const ReferenceParams sampleParams)
266{
267	const deUint32			textureWidth		= texture.getWidth() >> mipLevel;
268	const deUint32			textureHeight		= texture.getHeight() >> mipLevel;
269	const deUint32			renderWidth			= rendered.getWidth();
270	const deUint32			renderHeight		= rendered.getHeight();
271
272	tcu::TextureLevel		errorMaskStorage	(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), renderWidth, renderHeight, 1);
273	tcu::PixelBufferAccess	errorMask			= errorMaskStorage.getAccess();
274
275	tcu::UVec4				maxDiff				(0u, 0u, 0u, 0u);
276	tcu::UVec4				smpDiff				(0u, 0u, 0u, 0u);
277	tcu::UVec4				diff				(0u, 0u, 0u, 0u);
278	bool					isOk				= true;
279
280	// Compute reference.
281	tcu::Surface referenceFrame	(textureWidth, textureHeight);
282	glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat), texture, &texCoord[0], sampleParams);
283
284	for (deUint32 x = 0; x < renderWidth; ++x)
285	{
286		for (deUint32 y = 0; y < renderHeight; ++y)
287		{
288			bool			matchFound		= false;
289			const tcu::RGBA rendered_color	= rendered.getPixel(x, y);
290
291			const float	fragX			= ((float)x + 0.5f) / (float)renderWidth;
292			const float	fragY			= ((float)y + 0.5f) / (float)renderHeight;
293			const float	samplePixX		= fragX * (float)(textureWidth);
294			const float	samplePixY		= fragY * (float)(textureHeight);
295
296			const deUint32	sampleXMin		= (int)(samplePixX - coordThreshold);
297			const deUint32	sampleXMax		= (int)(samplePixX + coordThreshold);
298			const deUint32	sampleYMin		= (int)(samplePixY - coordThreshold);
299			const deUint32	sampleYMax		= (int)(samplePixY + coordThreshold);
300
301			// Compare color within given sample coordinates tolerance and return from included loops when match is found
302			for (deUint32 smpX = sampleXMin; smpX <= sampleXMax; ++smpX)
303			{
304				for (deUint32 smpY = sampleYMin; smpY <= sampleYMax; ++smpY)
305				{
306					const tcu::RGBA reference_color = referenceFrame.getPixel(smpX, smpY);
307
308					if (compareColor(reference_color, rendered_color, colorThreshold, diff))
309						matchFound = true;
310
311					smpDiff = min(smpDiff, diff);
312				}
313			}
314
315			maxDiff = tcu::max(maxDiff, smpDiff);
316			errorMask.setPixel(matchFound ? tcu::IVec4(0, 0xff, 0, 0xff) : tcu::IVec4(0xff, 0, 0, 0xff), x, y);
317
318			// Color mismatch
319			if (!matchFound)
320			{
321				isOk = false;
322			}
323		}
324	}
325
326	const tcu::ConstPixelBufferAccess	result			= rendered.getAccess();
327	const tcu::ConstPixelBufferAccess	reference		= referenceFrame.getAccess();
328	const char*							imageSetName	= "Result";
329	const char*							imageSetDesc	= "Image comparison result";
330	tcu::Vec4							pixelBias		(0.0f, 0.0f, 0.0f, 0.0f);
331	tcu::Vec4							pixelScale		(1.0f, 1.0f, 1.0f, 1.0f);
332
333	if (!isOk)
334	{
335		// All formats except normalized unsigned fixed point ones need remapping in order to fit into unorm channels in logged images.
336		if (tcu::getTextureChannelClass(reference.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
337			tcu::getTextureChannelClass(result.getFormat().type)	!= tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
338		{
339			computeScaleAndBias(reference, result, pixelScale, pixelBias);
340			log << TestLog::Message << "Result and reference images are normalized with formula p * " << pixelScale << " + " << pixelBias << TestLog::EndMessage;
341		}
342
343		log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", color threshold = " << colorThreshold.toIVec().cast<deUint32>()
344		<<  ", coordinates threshold = " << coordThreshold << TestLog::EndMessage;
345
346		log << TestLog::ImageSet(imageSetName, imageSetDesc)
347			<< TestLog::Image("Result",		"Result",		result)
348			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
349			<< TestLog::EndImageSet;
350	}
351	else
352	{
353		if (result.getFormat() != tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))
354			computePixelScaleBias(result, pixelScale, pixelBias);
355
356		log << TestLog::ImageSet(imageSetName, imageSetDesc)
357			<< TestLog::Image("Result",		"Result",		result,		pixelScale, pixelBias)
358			<< TestLog::EndImageSet;
359	}
360
361
362	return isOk;
363}
364
365tcu::TestStatus Compressed2DTestInstance::iterate (void)
366{
367	tcu::TestLog&					log				= m_context.getTestContext().getLog();
368	const pipeline::TestTexture2D&	texture			= m_renderer.get2DTexture(0);
369	const tcu::TextureFormat		textureFormat	= texture.getTextureFormat();
370	const tcu::TextureFormatInfo	formatInfo		= tcu::getTextureFormatInfo(textureFormat);
371	const deUint32					mipLevel		= m_testParameters.mipmaps ? 1 : 0;
372
373	ReferenceParams					sampleParams	(TEXTURETYPE_2D);
374	tcu::Surface					rendered		(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
375	vector<float>					texCoord;
376
377	// Setup params for reference.
378	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
379	sampleParams.samplerType		= SAMPLERTYPE_FLOAT;
380	sampleParams.lodMode			= LODMODE_EXACT;
381
382	if (m_testParameters.mipmaps) {
383		sampleParams.minLod = (float)mipLevel;
384		sampleParams.maxLod = (float)mipLevel;
385	}
386
387	if (isAstcFormat(m_compressedFormat)
388		|| m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK
389		|| m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK)
390	{
391		sampleParams.colorBias			= tcu::Vec4(0.0f);
392		sampleParams.colorScale			= tcu::Vec4(1.0f);
393	}
394	else if (m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK)
395	{
396		sampleParams.colorBias			= tcu::Vec4(0.5f, 0.0f, 0.0f, 0.0f);
397		sampleParams.colorScale			= tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f);
398	}
399	else if (m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK)
400	{
401		sampleParams.colorBias			= tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f);
402		sampleParams.colorScale			= tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f);
403	}
404	else
405	{
406		sampleParams.colorBias			= formatInfo.lookupBias;
407		sampleParams.colorScale			= formatInfo.lookupScale;
408	}
409
410	log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
411
412	// Compute texture coordinates.
413	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
414
415	m_renderer.renderQuad(rendered, 0, &texCoord[0], sampleParams);
416
417	// Compute reference.
418	const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
419	const tcu::PixelFormat	pixelFormat		(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
420
421#ifdef CTS_USES_VULKANSC
422	if (m_context.getTestContext().getCommandLine().isSubProcess())
423#endif // CTS_USES_VULKANSC
424	{
425		// Compare and log.
426		tcu::RGBA threshold;
427
428		if (isBcBitExactFormat(m_compressedFormat))
429			threshold = tcu::RGBA(1, 1, 1, 1);
430		else if (isBcFormat(m_compressedFormat))
431			threshold = tcu::RGBA(8, 8, 8, 8);
432		else
433			threshold = pixelFormat.getColorThreshold() + tcu::RGBA(2, 2, 2, 2);
434
435		constexpr float coordThreshold = 0.01f;
436		const bool isOk = validateTexture(log, rendered, texture.getTexture(), texCoord, mipLevel, pixelFormat, threshold, coordThreshold, sampleParams);
437
438		return isOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Image verification failed");
439	}
440	return tcu::TestStatus::pass("Pass");
441}
442
443class Compressed3DTestInstance : public TestInstance
444{
445public:
446	typedef Compressed3DTestParameters	ParameterType;
447
448										Compressed3DTestInstance	(Context&				context,
449																	 const ParameterType&	testParameters);
450	tcu::TestStatus						iterate						(void);
451
452private:
453										Compressed3DTestInstance	(const Compressed3DTestInstance& other);
454	Compressed3DTestInstance&			operator=					(const Compressed3DTestInstance& other);
455
456	const ParameterType&				m_testParameters;
457	const tcu::CompressedTexFormat		m_compressedFormat;
458	TestTexture3DSp						m_texture3D;
459	TextureRenderer						m_renderer2D;
460};
461
462Compressed3DTestInstance::Compressed3DTestInstance (Context&				context,
463													const ParameterType&	testParameters)
464	: TestInstance			(context)
465	, m_testParameters		(testParameters)
466	, m_compressedFormat	(mapVkCompressedFormat(testParameters.format))
467	, m_texture3D			(TestTexture3DSp(new pipeline::TestTexture3D(m_compressedFormat, testParameters.width, testParameters.height, testParameters.depth)))
468	, m_renderer2D			(context, testParameters.sampleCount, testParameters.width, testParameters.height, 1, makeComponentMappingRGBA(), VK_IMAGE_TYPE_2D, VK_IMAGE_VIEW_TYPE_2D)
469{
470	m_renderer2D.add3DTexture		(m_texture3D, testParameters.aspectMask, testParameters.backingMode);
471
472	VkPhysicalDeviceFeatures		physicalFeatures;
473	context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &physicalFeatures);
474
475	if (tcu::isAstcFormat(m_compressedFormat))
476	{
477		if (!physicalFeatures.textureCompressionASTC_LDR)
478			throw tcu::NotSupportedError(std::string("Unsupported format: ") + getFormatName(testParameters.format));
479	}
480	else if (tcu::isEtcFormat(m_compressedFormat))
481	{
482		if (!physicalFeatures.textureCompressionETC2)
483			throw tcu::NotSupportedError(std::string("Unsupported format: ") + getFormatName(testParameters.format));
484	}
485	else if(tcu::isBcFormat(m_compressedFormat))
486	{
487		if (!physicalFeatures.textureCompressionBC)
488			throw tcu::NotSupportedError(std::string("Unsupported format: ") + getFormatName(testParameters.format));
489	}
490	else
491	{
492		DE_FATAL("Unsupported compressed format");
493	}
494}
495
496tcu::TestStatus Compressed3DTestInstance::iterate (void)
497{
498	tcu::TestLog&					log				= m_context.getTestContext().getLog();
499	const pipeline::TestTexture3D&	texture			= m_renderer2D.get3DTexture(0);
500	const tcu::TextureFormat		textureFormat	= texture.getTextureFormat();
501	const tcu::TextureFormatInfo	formatInfo		= tcu::getTextureFormatInfo(textureFormat);
502	const deUint32					mipLevel		= m_testParameters.mipmaps ? 1 : 0;
503
504	ReferenceParams					sampleParams	(TEXTURETYPE_3D);
505	tcu::Surface					rendered		(m_renderer2D.getRenderWidth(), m_renderer2D.getRenderHeight());
506	vector<float>					texCoord;
507
508	// Setup params for reference.
509	sampleParams.sampler			= util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, m_testParameters.magFilter);
510	sampleParams.samplerType		= SAMPLERTYPE_FLOAT;
511	sampleParams.lodMode			= LODMODE_EXACT;
512
513	if (m_testParameters.mipmaps) {
514		sampleParams.minLod = (float)mipLevel;
515		sampleParams.maxLod = (float)mipLevel;
516	}
517
518	if (isAstcFormat(m_compressedFormat)
519		|| m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC4_UNORM_BLOCK
520		|| m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC5_UNORM_BLOCK)
521	{
522		sampleParams.colorBias			= tcu::Vec4(0.0f);
523		sampleParams.colorScale			= tcu::Vec4(1.0f);
524	}
525	else if (m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC4_SNORM_BLOCK)
526	{
527		sampleParams.colorBias			= tcu::Vec4(0.5f, 0.0f, 0.0f, 0.0f);
528		sampleParams.colorScale			= tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f);
529	}
530	else if (m_compressedFormat == tcu::COMPRESSEDTEXFORMAT_BC5_SNORM_BLOCK)
531	{
532		sampleParams.colorBias			= tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f);
533		sampleParams.colorScale			= tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f);
534	}
535	else
536	{
537		sampleParams.colorBias			= formatInfo.lookupBias;
538		sampleParams.colorScale			= formatInfo.lookupScale;
539	}
540
541	log << TestLog::Message << "Compare reference value = " << sampleParams.ref << TestLog::EndMessage;
542
543	constexpr deUint32		slices			= 3;
544	deUint32				sliceNdx		= 0;
545	float					z				= 0;
546	bool					isOk			= false;
547	const tcu::IVec4		formatBitDepth	= getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
548	const tcu::PixelFormat	pixelFormat	(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
549	tcu::RGBA				threshold;
550
551	if (isBcBitExactFormat(m_compressedFormat))
552		threshold = tcu::RGBA(1, 1, 1, 1);
553	else if (isBcSRGBFormat(m_compressedFormat))
554		threshold = tcu::RGBA(9, 9, 9, 9);
555	else if (isBcFormat(m_compressedFormat))
556		threshold = tcu::RGBA(8, 8, 8, 8);
557	else
558		threshold = pixelFormat.getColorThreshold() + tcu::RGBA(2, 2, 2, 2);
559
560	for (deUint32 s = 0; s < slices; ++s)
561	{
562		// Test different slices of 3D texture.
563
564		sliceNdx = (m_testParameters.depth - 1) * s / (slices - 1);
565
566		// Render texture.
567		z = (((float)sliceNdx + 0.5f) / (float)(m_testParameters.depth >> mipLevel));
568		computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, z), tcu::Vec3(1.0f, 1.0f, z), tcu::IVec3(0,1,2));
569		m_renderer2D.renderQuad(rendered, 0, &texCoord[0], sampleParams);
570
571		// Compare and log.
572#ifdef CTS_USES_VULKANSC
573		if (m_context.getTestContext().getCommandLine().isSubProcess())
574#endif // CTS_USES_VULKANSC
575		{
576			constexpr float coordThreshold = 0.01f;
577			isOk = validateTexture(log, rendered, m_texture3D->getTexture(), texCoord, mipLevel, pixelFormat, threshold, coordThreshold, sampleParams);
578
579			if (!isOk)
580				break;
581		}
582	}
583	return isOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Image verification failed");
584}
585
586} // anonymous
587
588void populateTextureCompressedFormatTests (tcu::TestCaseGroup* compressedTextureTests)
589{
590	tcu::TestContext&	testCtx	= compressedTextureTests->getTestContext();
591
592	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); sizeNdx++)
593	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
594	for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); backingNdx++)
595	{
596		const string	formatStr	= de::toString(getFormatStr(formats[formatNdx].format));
597		const string	nameBase	= de::toLower(formatStr.substr(10));
598
599		Compressed2DTestParameters	testParameters;
600		testParameters.format		= formats[formatNdx].format;
601		testParameters.backingMode	= backingModes[backingNdx].backingMode;
602		testParameters.width		= sizes[sizeNdx].width;
603		testParameters.height		= sizes[sizeNdx].height;
604		testParameters.minFilter	= tcu::Sampler::NEAREST_MIPMAP_NEAREST;
605		testParameters.magFilter	= tcu::Sampler::NEAREST;
606		testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
607		testParameters.programs.push_back(PROGRAM_2D_FLOAT);
608		testParameters.mipmaps		= sizes[sizeNdx].mipmaps;
609
610		compressedTextureTests->addChild(new TextureTestCase<Compressed2DTestInstance>(testCtx, (nameBase + "_2d_" + sizes[sizeNdx].name + backingModes[backingNdx].name).c_str(), testParameters));
611	}
612}
613
614void populate3DTextureCompressedFormatTests (tcu::TestCaseGroup* compressedTextureTests)
615{
616	tcu::TestContext&	testCtx	= compressedTextureTests->getTestContext();
617
618	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
619	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
620	for (int backingNdx = 0; backingNdx < DE_LENGTH_OF_ARRAY(backingModes); ++backingNdx)
621	{
622		const string	formatStr	= de::toString(getFormatStr(formats[formatNdx].format));
623		const string	nameBase	= de::toLower(formatStr.substr(10));
624
625		Compressed3DTestParameters	testParameters;
626		testParameters.format		= formats[formatNdx].format;
627		testParameters.backingMode	= backingModes[backingNdx].backingMode;
628		testParameters.width		= sizes[sizeNdx].width;
629		testParameters.height		= sizes[sizeNdx].height;
630		testParameters.depth		= sizes[sizeNdx].depth;
631		testParameters.minFilter	= tcu::Sampler::NEAREST_MIPMAP_NEAREST;
632		testParameters.magFilter	= tcu::Sampler::NEAREST;
633		testParameters.aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
634		testParameters.programs.push_back(PROGRAM_3D_FLOAT);
635		testParameters.mipmaps		= sizes[sizeNdx].mipmaps;
636
637		compressedTextureTests->addChild(new TextureTestCase<Compressed3DTestInstance>(testCtx, (nameBase + "_3d_" + sizes[sizeNdx].name + backingModes[backingNdx].name).c_str(), testParameters));
638	}
639}
640
641tcu::TestCaseGroup* createTextureCompressedFormatTests (tcu::TestContext& testCtx)
642{
643	return createTestGroup(testCtx, "compressed", populateTextureCompressedFormatTests);
644}
645
646tcu::TestCaseGroup* create3DTextureCompressedFormatTests (tcu::TestContext& testCtx)
647{
648	return createTestGroup(testCtx, "compressed_3D", populate3DTextureCompressedFormatTests);
649}
650
651} // texture
652} // vkt
653