• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief 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 
42 namespace vkt
43 {
44 namespace texture
45 {
46 namespace
47 {
48 
49 using namespace vk;
50 using namespace glu::TextureTestUtil;
51 using namespace texture::util;
52 
53 using std::string;
54 using std::vector;
55 using tcu::Sampler;
56 using tcu::TestLog;
57 
58 // Compressed formats
59 static 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 
122 static 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 
135 static 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 
146 struct Compressed3DTestParameters : public Texture3DTestCaseParameters
147 {
148 										Compressed3DTestParameters	(void);
149 	TextureBinding::ImageBackingMode	backingMode;
150 };
151 
Compressed3DTestParameters(void)152 Compressed3DTestParameters::Compressed3DTestParameters (void)
153 	: backingMode(TextureBinding::IMAGE_BACKING_MODE_REGULAR)
154 {
155 }
156 
157 struct Compressed2DTestParameters : public Texture2DTestCaseParameters
158 {
159 										Compressed2DTestParameters	(void);
160 	TextureBinding::ImageBackingMode	backingMode;
161 };
162 
Compressed2DTestParameters(void)163 Compressed2DTestParameters::Compressed2DTestParameters (void)
164 	: backingMode(TextureBinding::IMAGE_BACKING_MODE_REGULAR)
165 {
166 }
167 
168 class Compressed2DTestInstance : public TestInstance
169 {
170 public:
171 	typedef Compressed2DTestParameters	ParameterType;
172 
173 										Compressed2DTestInstance	(Context&				context,
174 																	 const ParameterType&	testParameters);
175 	tcu::TestStatus						iterate						(void);
176 
177 private:
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 
Compressed2DTestInstance(Context & context,const ParameterType & testParameters)187 Compressed2DTestInstance::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 
computeScaleAndBias(const tcu::ConstPixelBufferAccess & reference,const tcu::ConstPixelBufferAccess & result,tcu::Vec4 & scale,tcu::Vec4 & bias)198 static 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 
min(tcu::UVec4 a,tcu::UVec4 b)245 static 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 
compareColor(tcu::RGBA reference,tcu::RGBA result,tcu::RGBA threshold,tcu::UVec4 & diff)253 static 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 
263 template <typename TextureType>
validateTexture(tcu::TestLog & log,const tcu::Surface & rendered,const TextureType & texture,const vector<float> & texCoord,deUint32 mipLevel,const tcu::PixelFormat & pixelFormat,const tcu::RGBA & colorThreshold,float coordThreshold,const ReferenceParams sampleParams)264 static 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 
iterate(void)365 tcu::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 
443 class Compressed3DTestInstance : public TestInstance
444 {
445 public:
446 	typedef Compressed3DTestParameters	ParameterType;
447 
448 										Compressed3DTestInstance	(Context&				context,
449 																	 const ParameterType&	testParameters);
450 	tcu::TestStatus						iterate						(void);
451 
452 private:
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 
Compressed3DTestInstance(Context & context,const ParameterType & testParameters)462 Compressed3DTestInstance::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 
iterate(void)496 tcu::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 
populateTextureCompressedFormatTests(tcu::TestCaseGroup * compressedTextureTests)588 void 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(), (formatStr + ", TEXTURETYPE_2D").c_str(), testParameters));
611 	}
612 }
613 
populate3DTextureCompressedFormatTests(tcu::TestCaseGroup * compressedTextureTests)614 void 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(), (formatStr + ", TEXTURETYPE_3D").c_str(), testParameters));
638 	}
639 }
640 
createTextureCompressedFormatTests(tcu::TestContext & testCtx)641 tcu::TestCaseGroup* createTextureCompressedFormatTests (tcu::TestContext& testCtx)
642 {
643 	return createTestGroup(testCtx, "compressed", "Texture compressed format tests.", populateTextureCompressedFormatTests);
644 }
645 
create3DTextureCompressedFormatTests(tcu::TestContext & testCtx)646 tcu::TestCaseGroup* create3DTextureCompressedFormatTests (tcu::TestContext& testCtx)
647 {
648 	return createTestGroup(testCtx, "compressed_3D", "3D texture compressed format tests.", populate3DTextureCompressedFormatTests);
649 }
650 
651 } // texture
652 } // vkt
653