es3fASTCDecompressionCases.cpp revision c4eb6f3271a0bcd54835e666e836e3e72beebbd2
1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief ASTC decompression tests
22 *
23 * \todo Parts of the block-generation code are same as in decompression
24 *		 code in tcuCompressedTexture.cpp ; could put them to some shared
25 *		 ASTC utility file.
26 *
27 * \todo Tests for void extents with nontrivial extent coordinates.
28 *
29 * \todo Better checking of the error color. Currently legitimate error
30 *		 pixels are just ignored in image comparison; however, spec says
31 *		 that error color is either magenta or all-NaNs. Can NaNs cause
32 *		 troubles, or can we assume that NaNs are well-supported in shader
33 *		 if the implementation chooses NaNs as error color?
34 *//*--------------------------------------------------------------------*/
35
36#include "es3fASTCDecompressionCases.hpp"
37#include "gluTexture.hpp"
38#include "gluPixelTransfer.hpp"
39#include "gluStrUtil.hpp"
40#include "gluTextureUtil.hpp"
41#include "glsTextureTestUtil.hpp"
42#include "tcuCompressedTexture.hpp"
43#include "tcuTestLog.hpp"
44#include "tcuTextureUtil.hpp"
45#include "tcuSurface.hpp"
46#include "tcuVectorUtil.hpp"
47#include "tcuImageCompare.hpp"
48#include "deStringUtil.hpp"
49#include "deRandom.hpp"
50#include "deFloat16.h"
51#include "deString.h"
52#include "deMemory.h"
53
54#include "glwFunctions.hpp"
55#include "glwEnums.hpp"
56
57#include <vector>
58#include <string>
59#include <algorithm>
60
61using tcu::TestLog;
62using tcu::CompressedTexture;
63using tcu::CompressedTexFormat;
64using tcu::IVec2;
65using tcu::IVec3;
66using tcu::IVec4;
67using tcu::Vec2;
68using tcu::Vec4;
69using tcu::Sampler;
70using tcu::Surface;
71using tcu::astc::BlockTestType;
72using std::vector;
73using std::string;
74
75namespace deqp
76{
77
78using gls::TextureTestUtil::TextureRenderer;
79using gls::TextureTestUtil::RandomViewport;
80using namespace glu::TextureTestUtil;
81
82namespace gles3
83{
84namespace Functional
85{
86
87namespace ASTCDecompressionCaseInternal
88{
89
90// Get a string describing the data of an ASTC block. Currently contains just hex and bin dumps of the block.
91static string astcBlockDataStr (const deUint8* data)
92{
93	string result;
94	result += "  Hexadecimal (big endian: upper left hex digit is block bits 127 to 124):";
95
96	{
97		static const char* const hexDigits = "0123456789ABCDEF";
98
99		for (int i = tcu::astc::BLOCK_SIZE_BYTES-1; i >= 0; i--)
100		{
101			if ((i+1) % 2 == 0)
102				result += "\n    ";
103			else
104				result += "  ";
105
106			result += hexDigits[(data[i] & 0xf0) >> 4];
107			result += " ";
108			result += hexDigits[(data[i] & 0x0f) >> 0];
109		}
110	}
111
112	result += "\n\n  Binary (big endian: upper left bit is block bit 127):";
113
114	for (int i = tcu::astc::BLOCK_SIZE_BYTES-1; i >= 0; i--)
115	{
116		if ((i+1) % 2 == 0)
117			result += "\n    ";
118		else
119			result += "  ";
120
121		for (int j = 8-1; j >= 0; j--)
122		{
123			if (j == 3)
124				result += " ";
125
126			result += (data[i] >> j) & 1 ? "1" : "0";
127		}
128	}
129
130	result += "\n";
131
132	return result;
133}
134
135// Compare reference and result block images, reporting also the position of the first non-matching block.
136static bool compareBlockImages (const Surface&		reference,
137								const Surface&		result,
138								const tcu::RGBA&	thresholdRGBA,
139								const IVec2&		blockSize,
140								int					numNonDummyBlocks,
141								IVec2&				firstFailedBlockCoordDst,
142								Surface&			errorMaskDst,
143								IVec4&				maxDiffDst)
144{
145	TCU_CHECK_INTERNAL(reference.getWidth() == result.getWidth() && reference.getHeight() == result.getHeight());
146
147	const int		width		= result.getWidth();
148	const int		height		= result.getHeight();
149	const IVec4		threshold	= thresholdRGBA.toIVec();
150	const int		numXBlocks	= width / blockSize.x();
151
152	DE_ASSERT(width % blockSize.x() == 0 && height % blockSize.y() == 0);
153
154	errorMaskDst.setSize(width, height);
155
156	firstFailedBlockCoordDst	= IVec2(-1, -1);
157	maxDiffDst					= IVec4(0);
158
159	for (int y = 0; y < height; y++)
160	for (int x = 0; x < width; x++)
161	{
162		const IVec2 blockCoord = IVec2(x, y) / blockSize;
163
164		if (blockCoord.y()*numXBlocks + blockCoord.x() < numNonDummyBlocks)
165		{
166			const IVec4 refPix = reference.getPixel(x, y).toIVec();
167
168			if (refPix == IVec4(255, 0, 255, 255))
169			{
170				// ASTC error color - allow anything in result.
171				errorMaskDst.setPixel(x, y, tcu::RGBA(255, 0, 255, 255));
172				continue;
173			}
174
175			const IVec4		resPix		= result.getPixel(x, y).toIVec();
176			const IVec4		diff		= tcu::abs(refPix - resPix);
177			const bool		isOk		= tcu::boolAll(tcu::lessThanEqual(diff, threshold));
178
179			maxDiffDst = tcu::max(maxDiffDst, diff);
180
181			errorMaskDst.setPixel(x, y, isOk ? tcu::RGBA::green() : tcu::RGBA::red());
182
183			if (!isOk && firstFailedBlockCoordDst.x() == -1)
184				firstFailedBlockCoordDst = blockCoord;
185		}
186	}
187
188	return boolAll(lessThanEqual(maxDiffDst, threshold));
189}
190
191enum ASTCSupportLevel
192{
193	// \note Ordered from smallest subset to full, for convenient comparison.
194	ASTCSUPPORTLEVEL_NONE = 0,
195	ASTCSUPPORTLEVEL_LDR,
196	ASTCSUPPORTLEVEL_HDR,
197	ASTCSUPPORTLEVEL_FULL
198};
199
200static inline ASTCSupportLevel getASTCSupportLevel (const glu::ContextInfo& contextInfo, const glu::RenderContext& renderCtx)
201{
202	const bool isES32 = glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3, 2));
203
204	const vector<string>& extensions = contextInfo.getExtensions();
205
206	ASTCSupportLevel maxLevel = ASTCSUPPORTLEVEL_NONE;
207
208	for (int extNdx = 0; extNdx < (int)extensions.size(); extNdx++)
209	{
210		const string& ext = extensions[extNdx];
211		if (isES32)
212		{
213			maxLevel =	de::max(maxLevel, ext == "GL_KHR_texture_compression_astc_hdr"	? ASTCSUPPORTLEVEL_HDR
214										: ext == "GL_OES_texture_compression_astc"		? ASTCSUPPORTLEVEL_FULL
215										: ASTCSUPPORTLEVEL_LDR);
216		}
217		else
218		{
219			maxLevel =	de::max(maxLevel, ext == "GL_KHR_texture_compression_astc_ldr"	? ASTCSUPPORTLEVEL_LDR
220										: ext == "GL_KHR_texture_compression_astc_hdr"	? ASTCSUPPORTLEVEL_HDR
221										: ext == "GL_OES_texture_compression_astc"		? ASTCSUPPORTLEVEL_FULL
222										: ASTCSUPPORTLEVEL_NONE);
223		}
224	}
225
226	return maxLevel;
227}
228
229// Class handling the common rendering stuff of ASTC cases.
230class ASTCRenderer2D
231{
232public:
233								ASTCRenderer2D		(Context&				context,
234													 CompressedTexFormat	format,
235													 deUint32				randomSeed);
236
237								~ASTCRenderer2D		(void);
238
239	void						initialize			(int minRenderWidth, int minRenderHeight, const Vec4& colorScale, const Vec4& colorBias);
240	void						clear				(void);
241
242	void						render				(Surface&					referenceDst,
243													 Surface&					resultDst,
244													 const glu::Texture2D&		texture,
245													 const tcu::TextureFormat&	uncompressedFormat);
246
247	CompressedTexFormat			getFormat			(void) const { return m_format; }
248	IVec2						getBlockSize		(void) const { return m_blockSize; }
249	ASTCSupportLevel			getASTCSupport		(void) const { DE_ASSERT(m_initialized); return m_astcSupport;	}
250
251private:
252	Context&					m_context;
253	TextureRenderer				m_renderer;
254
255	const CompressedTexFormat	m_format;
256	const IVec2					m_blockSize;
257	ASTCSupportLevel			m_astcSupport;
258	Vec4						m_colorScale;
259	Vec4						m_colorBias;
260
261	de::Random					m_rnd;
262
263	bool						m_initialized;
264};
265
266} // ASTCDecompressionCaseInternal
267
268using namespace ASTCDecompressionCaseInternal;
269
270ASTCRenderer2D::ASTCRenderer2D (Context&			context,
271								CompressedTexFormat	format,
272								deUint32			randomSeed)
273	: m_context			(context)
274	, m_renderer		(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_HIGHP)
275	, m_format			(format)
276	, m_blockSize		(tcu::getBlockPixelSize(format).xy())
277	, m_astcSupport		(ASTCSUPPORTLEVEL_NONE)
278	, m_colorScale		(-1.0f)
279	, m_colorBias		(-1.0f)
280	, m_rnd				(randomSeed)
281	, m_initialized		(false)
282{
283	DE_ASSERT(tcu::getBlockPixelSize(format).z() == 1);
284}
285
286ASTCRenderer2D::~ASTCRenderer2D (void)
287{
288	clear();
289}
290
291void ASTCRenderer2D::initialize (int minRenderWidth, int minRenderHeight, const Vec4& colorScale, const Vec4& colorBias)
292{
293	DE_ASSERT(!m_initialized);
294
295	const tcu::RenderTarget&	renderTarget	= m_context.getRenderTarget();
296	TestLog&					log				= m_context.getTestContext().getLog();
297
298	m_astcSupport	= getASTCSupportLevel(m_context.getContextInfo(), m_context.getRenderContext());
299	m_colorScale	= colorScale;
300	m_colorBias		= colorBias;
301
302	switch (m_astcSupport)
303	{
304		case ASTCSUPPORTLEVEL_NONE:		log << TestLog::Message << "No ASTC support detected" << TestLog::EndMessage;		throw tcu::NotSupportedError("ASTC not supported");
305		case ASTCSUPPORTLEVEL_LDR:		log << TestLog::Message << "LDR ASTC support detected" << TestLog::EndMessage;		break;
306		case ASTCSUPPORTLEVEL_HDR:		log << TestLog::Message << "HDR ASTC support detected" << TestLog::EndMessage;		break;
307		case ASTCSUPPORTLEVEL_FULL:		log << TestLog::Message << "Full ASTC support detected" << TestLog::EndMessage;		break;
308		default:
309			DE_ASSERT(false);
310	}
311
312	if (renderTarget.getWidth() < minRenderWidth || renderTarget.getHeight() < minRenderHeight)
313		throw tcu::NotSupportedError("Render target must be at least " + de::toString(minRenderWidth) + "x" + de::toString(minRenderHeight));
314
315	log << TestLog::Message << "Using color scale and bias: result = raw * " << colorScale << " + " << colorBias << TestLog::EndMessage;
316
317	m_initialized = true;
318}
319
320void ASTCRenderer2D::clear (void)
321{
322	m_renderer.clear();
323}
324
325void ASTCRenderer2D::render (Surface& referenceDst, Surface& resultDst, const glu::Texture2D& texture, const tcu::TextureFormat& uncompressedFormat)
326{
327	DE_ASSERT(m_initialized);
328
329	const glw::Functions&			gl						= m_context.getRenderContext().getFunctions();
330	const glu::RenderContext&		renderCtx				= m_context.getRenderContext();
331	const int						textureWidth			= texture.getRefTexture().getWidth();
332	const int						textureHeight			= texture.getRefTexture().getHeight();
333	const RandomViewport			viewport				(renderCtx.getRenderTarget(), textureWidth, textureHeight, m_rnd.getUint32());
334	ReferenceParams					renderParams			(TEXTURETYPE_2D);
335	vector<float>					texCoord;
336	computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
337
338	renderParams.samplerType	= getSamplerType(uncompressedFormat);
339	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
340	renderParams.colorScale		= m_colorScale;
341	renderParams.colorBias		= m_colorBias;
342
343	// Setup base viewport.
344	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
345
346	// Bind to unit 0.
347	gl.activeTexture(GL_TEXTURE0);
348	gl.bindTexture(GL_TEXTURE_2D, texture.getGLTexture());
349
350	// Setup nearest neighbor filtering and clamp-to-edge.
351	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
352	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
353	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
354	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
355
356	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
357
358	// Issue GL draws.
359	m_renderer.renderQuad(0, &texCoord[0], renderParams);
360	gl.flush();
361
362	// Compute reference.
363	sampleTexture(tcu::SurfaceAccess(referenceDst, renderCtx.getRenderTarget().getPixelFormat()), texture.getRefTexture(), &texCoord[0], renderParams);
364
365	// Read GL-rendered image.
366	glu::readPixels(renderCtx, viewport.x, viewport.y, resultDst.getAccess());
367}
368
369ASTCBlockCase2D::ASTCBlockCase2D (Context&				context,
370								  const char*			name,
371								  const char*			description,
372								  BlockTestType			testType,
373								  CompressedTexFormat	format)
374	: TestCase				(context, name, description)
375	, m_testType			(testType)
376	, m_format				(format)
377	, m_numBlocksTested		(0)
378	, m_currentIteration	(0)
379	, m_renderer			(new ASTCRenderer2D(context, format, deStringHash(getName())))
380{
381	DE_ASSERT(!(tcu::isAstcSRGBFormat(m_format) && tcu::astc::isBlockTestTypeHDROnly(m_testType))); // \note There is no HDR sRGB mode, so these would be redundant.
382}
383
384ASTCBlockCase2D::~ASTCBlockCase2D (void)
385{
386	ASTCBlockCase2D::deinit();
387}
388
389void ASTCBlockCase2D::init (void)
390{
391	m_renderer->initialize(64, 64, tcu::astc::getBlockTestTypeColorScale(m_testType), tcu::astc::getBlockTestTypeColorBias(m_testType));
392
393	generateBlockCaseTestData(m_blockData, m_format, m_testType);
394	DE_ASSERT(!m_blockData.empty());
395	DE_ASSERT(m_blockData.size() % tcu::astc::BLOCK_SIZE_BYTES == 0);
396
397	m_testCtx.getLog() << TestLog::Message << "Total " << m_blockData.size() / tcu::astc::BLOCK_SIZE_BYTES << " blocks to test" << TestLog::EndMessage
398					   << TestLog::Message << "Note: Legitimate ASTC error pixels will be ignored when comparing to reference" << TestLog::EndMessage;
399}
400
401void ASTCBlockCase2D::deinit (void)
402{
403	m_renderer->clear();
404	m_blockData.clear();
405}
406
407ASTCBlockCase2D::IterateResult ASTCBlockCase2D::iterate (void)
408{
409	TestLog&						log						= m_testCtx.getLog();
410
411	if (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR && tcu::astc::isBlockTestTypeHDROnly(m_testType))
412	{
413		log << TestLog::Message << "Passing the case immediately, since only LDR support was detected and test only contains HDR blocks" << TestLog::EndMessage;
414		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
415		return STOP;
416	}
417
418	const IVec2						blockSize				= m_renderer->getBlockSize();
419	const int						totalNumBlocks			= (int)m_blockData.size() / tcu::astc::BLOCK_SIZE_BYTES;
420	const int						numXBlocksPerImage		= de::min(m_context.getRenderTarget().getWidth(),  512) / blockSize.x();
421	const int						numYBlocksPerImage		= de::min(m_context.getRenderTarget().getHeight(), 512) / blockSize.y();
422	const int						numBlocksPerImage		= numXBlocksPerImage * numYBlocksPerImage;
423	const int						imageWidth				= numXBlocksPerImage * blockSize.x();
424	const int						imageHeight				= numYBlocksPerImage * blockSize.y();
425	const int						numBlocksRemaining		= totalNumBlocks - m_numBlocksTested;
426	const int						curNumNonDummyBlocks	= de::min(numBlocksPerImage, numBlocksRemaining);
427	const int						curNumDummyBlocks		= numBlocksPerImage - curNumNonDummyBlocks;
428	const glu::RenderContext&		renderCtx				= m_context.getRenderContext();
429	const tcu::RGBA					threshold				= renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + (tcu::isAstcSRGBFormat(m_format) ? tcu::RGBA(2,2,2,2) : tcu::RGBA(1,1,1,1));
430	tcu::CompressedTexture			compressed				(m_format, imageWidth, imageHeight);
431
432	if (m_currentIteration == 0)
433	{
434		log << TestLog::Message << "Using texture of size "
435								<< imageWidth << "x" << imageHeight
436								<< ", with " << numXBlocksPerImage << " block columns and " << numYBlocksPerImage << " block rows "
437								<< ", with block size " << blockSize.x() << "x" << blockSize.y()
438			<< TestLog::EndMessage;
439	}
440
441	DE_ASSERT(compressed.getDataSize() == numBlocksPerImage*tcu::astc::BLOCK_SIZE_BYTES);
442	deMemcpy(compressed.getData(), &m_blockData[m_numBlocksTested*tcu::astc::BLOCK_SIZE_BYTES], curNumNonDummyBlocks*tcu::astc::BLOCK_SIZE_BYTES);
443	if (curNumDummyBlocks > 1)
444		tcu::astc::generateDummyVoidExtentBlocks((deUint8*)compressed.getData() + curNumNonDummyBlocks*tcu::astc::BLOCK_SIZE_BYTES, curNumDummyBlocks);
445
446	// Create texture and render.
447
448	glu::Texture2D	texture			(renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams((m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR ? tcu::TexDecompressionParams::ASTCMODE_LDR : tcu::TexDecompressionParams::ASTCMODE_HDR)));
449	Surface			renderedFrame	(imageWidth, imageHeight);
450	Surface			referenceFrame	(imageWidth, imageHeight);
451
452	m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
453
454	// Compare and log.
455	// \note Since a case can draw quite many images, only log the first iteration and failures.
456
457	{
458		Surface		errorMask;
459		IVec2		firstFailedBlockCoord;
460		IVec4		maxDiff;
461		const bool	compareOk = compareBlockImages(referenceFrame, renderedFrame, threshold, blockSize, curNumNonDummyBlocks, firstFailedBlockCoord, errorMask, maxDiff);
462
463		if (m_currentIteration == 0 || !compareOk)
464		{
465			const char* const		imageSetName	= "ComparisonResult";
466			const char* const		imageSetDesc	= "Comparison Result";
467
468			{
469				tcu::ScopedLogSection section(log, "Iteration " + de::toString(m_currentIteration),
470													"Blocks " + de::toString(m_numBlocksTested) + " to " + de::toString(m_numBlocksTested + curNumNonDummyBlocks - 1));
471
472				if (curNumDummyBlocks > 0)
473					log << TestLog::Message << "Note: Only the first " << curNumNonDummyBlocks << " blocks in the image are relevant; rest " << curNumDummyBlocks << " are dummies and not checked" << TestLog::EndMessage;
474
475				if (!compareOk)
476				{
477					log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff << ", threshold = " << threshold << TestLog::EndMessage
478						<< TestLog::ImageSet(imageSetName, imageSetDesc)
479						<< TestLog::Image("Result",		"Result",		renderedFrame)
480						<< TestLog::Image("Reference",	"Reference",	referenceFrame)
481						<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
482						<< TestLog::EndImageSet;
483
484					const int blockNdx = m_numBlocksTested + firstFailedBlockCoord.y()*numXBlocksPerImage + firstFailedBlockCoord.x();
485					DE_ASSERT(blockNdx < totalNumBlocks);
486
487					log << TestLog::Message << "First failed block at column " << firstFailedBlockCoord.x() << " and row " << firstFailedBlockCoord.y() << TestLog::EndMessage
488						<< TestLog::Message << "Data of first failed block:\n" << astcBlockDataStr(&m_blockData[blockNdx*tcu::astc::BLOCK_SIZE_BYTES]) << TestLog::EndMessage;
489
490					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
491					return STOP;
492				}
493				else
494				{
495					log << TestLog::ImageSet(imageSetName, imageSetDesc)
496						<< TestLog::Image("Result", "Result", renderedFrame)
497						<< TestLog::EndImageSet;
498				}
499			}
500
501			if (m_numBlocksTested + curNumNonDummyBlocks < totalNumBlocks)
502				log << TestLog::Message << "Note: not logging further images unless reference comparison fails" << TestLog::EndMessage;
503		}
504	}
505
506	m_currentIteration++;
507	m_numBlocksTested += curNumNonDummyBlocks;
508
509	if (m_numBlocksTested >= totalNumBlocks)
510	{
511		DE_ASSERT(m_numBlocksTested == totalNumBlocks);
512		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
513		return STOP;
514	}
515
516	return CONTINUE;
517}
518
519
520
521ASTCBlockSizeRemainderCase2D::ASTCBlockSizeRemainderCase2D (Context&			context,
522															const char*			name,
523															const char*			description,
524															CompressedTexFormat	format)
525	: TestCase				(context, name, description)
526	, m_format				(format)
527	, m_currentIteration	(0)
528	, m_renderer			(new ASTCRenderer2D(context, format, deStringHash(getName())))
529{
530}
531
532ASTCBlockSizeRemainderCase2D::~ASTCBlockSizeRemainderCase2D (void)
533{
534	ASTCBlockSizeRemainderCase2D::deinit();
535}
536
537void ASTCBlockSizeRemainderCase2D::init (void)
538{
539	const IVec2 blockSize = m_renderer->getBlockSize();
540	m_renderer->initialize(MAX_NUM_BLOCKS_X*blockSize.x(), MAX_NUM_BLOCKS_Y*blockSize.y(), Vec4(1.0f), Vec4(0.0f));
541}
542
543void ASTCBlockSizeRemainderCase2D::deinit (void)
544{
545	m_renderer->clear();
546}
547
548ASTCBlockSizeRemainderCase2D::IterateResult ASTCBlockSizeRemainderCase2D::iterate (void)
549{
550	TestLog&						log						= m_testCtx.getLog();
551	const IVec2						blockSize				= m_renderer->getBlockSize();
552	const int						curRemainderX			= m_currentIteration % blockSize.x();
553	const int						curRemainderY			= m_currentIteration / blockSize.x();
554	const int						imageWidth				= (MAX_NUM_BLOCKS_X-1)*blockSize.x() + curRemainderX;
555	const int						imageHeight				= (MAX_NUM_BLOCKS_Y-1)*blockSize.y() + curRemainderY;
556	const int						numBlocksX				= deDivRoundUp32(imageWidth, blockSize.x());
557	const int						numBlocksY				= deDivRoundUp32(imageHeight, blockSize.y());
558	const int						totalNumBlocks			= numBlocksX * numBlocksY;
559	const glu::RenderContext&		renderCtx				= m_context.getRenderContext();
560	const tcu::RGBA					threshold				= renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + (tcu::isAstcSRGBFormat(m_format) ? tcu::RGBA(2,2,2,2) : tcu::RGBA(1,1,1,1));
561	tcu::CompressedTexture			compressed				(m_format, imageWidth, imageHeight);
562
563	DE_ASSERT(compressed.getDataSize() == totalNumBlocks*tcu::astc::BLOCK_SIZE_BYTES);
564	tcu::astc::generateDummyNormalBlocks((deUint8*)compressed.getData(), totalNumBlocks, blockSize.x(), blockSize.y());
565
566	// Create texture and render.
567
568	Surface			renderedFrame	(imageWidth, imageHeight);
569	Surface			referenceFrame	(imageWidth, imageHeight);
570	glu::Texture2D	texture			(renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR ? tcu::TexDecompressionParams::ASTCMODE_LDR : tcu::TexDecompressionParams::ASTCMODE_HDR));
571
572	m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
573
574	{
575		// Compare and log.
576
577		tcu::ScopedLogSection section(log, "Iteration " + de::toString(m_currentIteration),
578										   "Remainder " + de::toString(curRemainderX) + "x" + de::toString(curRemainderY));
579
580		log << TestLog::Message << "Using texture of size "
581								<< imageWidth << "x" << imageHeight
582								<< " and block size "
583								<< blockSize.x() << "x" << blockSize.y()
584								<< "; the x and y remainders are "
585								<< curRemainderX << " and " << curRemainderY << " respectively"
586			<< TestLog::EndMessage;
587
588		const bool compareOk = tcu::pixelThresholdCompare(m_testCtx.getLog(), "ComparisonResult", "Comparison Result", referenceFrame, renderedFrame, threshold,
589														  m_currentIteration == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
590
591		if (!compareOk)
592		{
593			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
594			return STOP;
595		}
596	}
597
598	if (m_currentIteration == 0 && m_currentIteration+1 < blockSize.x()*blockSize.y())
599		log << TestLog::Message << "Note: not logging further images unless reference comparison fails" << TestLog::EndMessage;
600
601	m_currentIteration++;
602
603	if (m_currentIteration >= blockSize.x()*blockSize.y())
604	{
605		DE_ASSERT(m_currentIteration == blockSize.x()*blockSize.y());
606		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
607		return STOP;
608	}
609	return CONTINUE;
610}
611
612} // Functional
613} // gles3
614} // deqp
615