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
61 using std::string;
62 using std::vector;
63 using tcu::CompressedTexFormat;
64 using tcu::CompressedTexture;
65 using tcu::IVec2;
66 using tcu::IVec3;
67 using tcu::IVec4;
68 using tcu::Sampler;
69 using tcu::Surface;
70 using tcu::TestLog;
71 using tcu::Vec2;
72 using tcu::Vec4;
73 using tcu::astc::BlockTestType;
74
75 namespace deqp
76 {
77
78 using gls::TextureTestUtil::RandomViewport;
79 using gls::TextureTestUtil::TextureRenderer;
80 using namespace glu::TextureTestUtil;
81
82 namespace gles3
83 {
84 namespace Functional
85 {
86
87 namespace ASTCDecompressionCaseInternal
88 {
89
90 // Get a string describing the data of an ASTC block. Currently contains just hex and bin dumps of the block.
astcBlockDataStr(const uint8_t * data)91 static string astcBlockDataStr(const uint8_t *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.
compareBlockImages(const Surface & reference,const Surface & result,const tcu::RGBA & thresholdRGBA,const IVec2 & blockSize,int numUsedBlocks,IVec2 & firstFailedBlockCoordDst,Surface & errorMaskDst,IVec4 & maxDiffDst)136 static bool compareBlockImages(const Surface &reference, const Surface &result, const tcu::RGBA &thresholdRGBA,
137 const IVec2 &blockSize, int numUsedBlocks, IVec2 &firstFailedBlockCoordDst,
138 Surface &errorMaskDst, IVec4 &maxDiffDst)
139 {
140 TCU_CHECK_INTERNAL(reference.getWidth() == result.getWidth() && reference.getHeight() == result.getHeight());
141
142 const int width = result.getWidth();
143 const int height = result.getHeight();
144 const IVec4 threshold = thresholdRGBA.toIVec();
145 const int numXBlocks = width / blockSize.x();
146
147 DE_ASSERT(width % blockSize.x() == 0 && height % blockSize.y() == 0);
148
149 errorMaskDst.setSize(width, height);
150
151 firstFailedBlockCoordDst = IVec2(-1, -1);
152 maxDiffDst = IVec4(0);
153
154 for (int y = 0; y < height; y++)
155 for (int x = 0; x < width; x++)
156 {
157 const IVec2 blockCoord = IVec2(x, y) / blockSize;
158
159 if (blockCoord.y() * numXBlocks + blockCoord.x() < numUsedBlocks)
160 {
161 const IVec4 refPix = reference.getPixel(x, y).toIVec();
162
163 if (refPix == IVec4(255, 0, 255, 255))
164 {
165 // ASTC error color - allow anything in result.
166 errorMaskDst.setPixel(x, y, tcu::RGBA(255, 0, 255, 255));
167 continue;
168 }
169
170 const IVec4 resPix = result.getPixel(x, y).toIVec();
171 const IVec4 diff = tcu::abs(refPix - resPix);
172 const bool isOk = tcu::boolAll(tcu::lessThanEqual(diff, threshold));
173
174 maxDiffDst = tcu::max(maxDiffDst, diff);
175
176 errorMaskDst.setPixel(x, y, isOk ? tcu::RGBA::green() : tcu::RGBA::red());
177
178 if (!isOk && firstFailedBlockCoordDst.x() == -1)
179 firstFailedBlockCoordDst = blockCoord;
180 }
181 }
182
183 return boolAll(lessThanEqual(maxDiffDst, threshold));
184 }
185
186 enum ASTCSupportLevel
187 {
188 // \note Ordered from smallest subset to full, for convenient comparison.
189 ASTCSUPPORTLEVEL_NONE = 0,
190 ASTCSUPPORTLEVEL_LDR,
191 ASTCSUPPORTLEVEL_HDR,
192 ASTCSUPPORTLEVEL_FULL
193 };
194
getASTCSupportLevel(const glu::ContextInfo & contextInfo,const glu::RenderContext & renderCtx)195 static inline ASTCSupportLevel getASTCSupportLevel(const glu::ContextInfo &contextInfo,
196 const glu::RenderContext &renderCtx)
197 {
198 const bool isES32 = glu::contextSupports(renderCtx.getType(), glu::ApiType::es(3, 2));
199
200 const vector<string> &extensions = contextInfo.getExtensions();
201
202 ASTCSupportLevel maxLevel = ASTCSUPPORTLEVEL_NONE;
203
204 for (int extNdx = 0; extNdx < (int)extensions.size(); extNdx++)
205 {
206 const string &ext = extensions[extNdx];
207 if (isES32)
208 {
209 maxLevel = de::max(maxLevel, ext == "GL_KHR_texture_compression_astc_hdr" ? ASTCSUPPORTLEVEL_HDR :
210 ext == "GL_OES_texture_compression_astc" ? ASTCSUPPORTLEVEL_FULL :
211 ASTCSUPPORTLEVEL_LDR);
212 }
213 else
214 {
215 maxLevel = de::max(maxLevel, ext == "GL_KHR_texture_compression_astc_ldr" ? ASTCSUPPORTLEVEL_LDR :
216 ext == "GL_KHR_texture_compression_astc_hdr" ? ASTCSUPPORTLEVEL_HDR :
217 ext == "GL_OES_texture_compression_astc" ? ASTCSUPPORTLEVEL_FULL :
218 ASTCSUPPORTLEVEL_NONE);
219 }
220 }
221
222 return maxLevel;
223 }
224
225 // Class handling the common rendering stuff of ASTC cases.
226 class ASTCRenderer2D
227 {
228 public:
229 ASTCRenderer2D(Context &context, CompressedTexFormat format, uint32_t randomSeed);
230
231 ~ASTCRenderer2D(void);
232
233 void initialize(int minRenderWidth, int minRenderHeight, const Vec4 &colorScale, const Vec4 &colorBias);
234 void clear(void);
235
236 void render(Surface &referenceDst, Surface &resultDst, const glu::Texture2D &texture,
237 const tcu::TextureFormat &uncompressedFormat);
238
getFormat(void) const239 CompressedTexFormat getFormat(void) const
240 {
241 return m_format;
242 }
getBlockSize(void) const243 IVec2 getBlockSize(void) const
244 {
245 return m_blockSize;
246 }
getASTCSupport(void) const247 ASTCSupportLevel getASTCSupport(void) const
248 {
249 DE_ASSERT(m_initialized);
250 return m_astcSupport;
251 }
252
253 private:
254 Context &m_context;
255 TextureRenderer m_renderer;
256
257 const CompressedTexFormat m_format;
258 const IVec2 m_blockSize;
259 ASTCSupportLevel m_astcSupport;
260 Vec4 m_colorScale;
261 Vec4 m_colorBias;
262
263 de::Random m_rnd;
264
265 bool m_initialized;
266 };
267
268 } // namespace ASTCDecompressionCaseInternal
269
270 using namespace ASTCDecompressionCaseInternal;
271
ASTCRenderer2D(Context & context,CompressedTexFormat format,uint32_t randomSeed)272 ASTCRenderer2D::ASTCRenderer2D(Context &context, CompressedTexFormat format, uint32_t randomSeed)
273 : m_context(context)
274 , m_renderer(context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_300_ES,
275 glu::PRECISION_HIGHP)
276 , m_format(format)
277 , m_blockSize(tcu::getBlockPixelSize(format).xy())
278 , m_astcSupport(ASTCSUPPORTLEVEL_NONE)
279 , m_colorScale(-1.0f)
280 , m_colorBias(-1.0f)
281 , m_rnd(randomSeed)
282 , m_initialized(false)
283 {
284 DE_ASSERT(tcu::getBlockPixelSize(format).z() == 1);
285 }
286
~ASTCRenderer2D(void)287 ASTCRenderer2D::~ASTCRenderer2D(void)
288 {
289 clear();
290 }
291
initialize(int minRenderWidth,int minRenderHeight,const Vec4 & colorScale,const Vec4 & colorBias)292 void ASTCRenderer2D::initialize(int minRenderWidth, int minRenderHeight, const Vec4 &colorScale, const Vec4 &colorBias)
293 {
294 DE_ASSERT(!m_initialized);
295
296 const tcu::RenderTarget &renderTarget = m_context.getRenderTarget();
297 TestLog &log = m_context.getTestContext().getLog();
298
299 m_astcSupport = getASTCSupportLevel(m_context.getContextInfo(), m_context.getRenderContext());
300 m_colorScale = colorScale;
301 m_colorBias = colorBias;
302
303 switch (m_astcSupport)
304 {
305 case ASTCSUPPORTLEVEL_NONE:
306 log << TestLog::Message << "No ASTC support detected" << TestLog::EndMessage;
307 throw tcu::NotSupportedError("ASTC not supported");
308 case ASTCSUPPORTLEVEL_LDR:
309 log << TestLog::Message << "LDR ASTC support detected" << TestLog::EndMessage;
310 break;
311 case ASTCSUPPORTLEVEL_HDR:
312 log << TestLog::Message << "HDR ASTC support detected" << TestLog::EndMessage;
313 break;
314 case ASTCSUPPORTLEVEL_FULL:
315 log << TestLog::Message << "Full ASTC support detected" << TestLog::EndMessage;
316 break;
317 default:
318 DE_ASSERT(false);
319 }
320
321 if (renderTarget.getWidth() < minRenderWidth || renderTarget.getHeight() < minRenderHeight)
322 throw tcu::NotSupportedError("Render target must be at least " + de::toString(minRenderWidth) + "x" +
323 de::toString(minRenderHeight));
324
325 log << TestLog::Message << "Using color scale and bias: result = raw * " << colorScale << " + " << colorBias
326 << TestLog::EndMessage;
327
328 m_initialized = true;
329 }
330
clear(void)331 void ASTCRenderer2D::clear(void)
332 {
333 m_renderer.clear();
334 }
335
render(Surface & referenceDst,Surface & resultDst,const glu::Texture2D & texture,const tcu::TextureFormat & uncompressedFormat)336 void ASTCRenderer2D::render(Surface &referenceDst, Surface &resultDst, const glu::Texture2D &texture,
337 const tcu::TextureFormat &uncompressedFormat)
338 {
339 DE_ASSERT(m_initialized);
340
341 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
342 const glu::RenderContext &renderCtx = m_context.getRenderContext();
343 const int textureWidth = texture.getRefTexture().getWidth();
344 const int textureHeight = texture.getRefTexture().getHeight();
345 const RandomViewport viewport(renderCtx.getRenderTarget(), textureWidth, textureHeight, m_rnd.getUint32());
346 ReferenceParams renderParams(TEXTURETYPE_2D);
347 vector<float> texCoord;
348 computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
349
350 renderParams.samplerType = getSamplerType(uncompressedFormat);
351 renderParams.sampler = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE,
352 Sampler::NEAREST, Sampler::NEAREST);
353 renderParams.colorScale = m_colorScale;
354 renderParams.colorBias = m_colorBias;
355
356 // Setup base viewport.
357 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
358
359 // Bind to unit 0.
360 gl.activeTexture(GL_TEXTURE0);
361 gl.bindTexture(GL_TEXTURE_2D, texture.getGLTexture());
362
363 // Setup nearest neighbor filtering and clamp-to-edge.
364 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
365 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
366 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
367 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
368
369 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
370
371 // Issue GL draws.
372 m_renderer.renderQuad(0, &texCoord[0], renderParams);
373 gl.flush();
374
375 // Compute reference.
376 sampleTexture(tcu::SurfaceAccess(referenceDst, renderCtx.getRenderTarget().getPixelFormat()),
377 texture.getRefTexture(), &texCoord[0], renderParams);
378
379 // Read GL-rendered image.
380 glu::readPixels(renderCtx, viewport.x, viewport.y, resultDst.getAccess());
381 }
382
ASTCBlockCase2D(Context & context,const char * name,const char * description,BlockTestType testType,CompressedTexFormat format)383 ASTCBlockCase2D::ASTCBlockCase2D(Context &context, const char *name, const char *description, BlockTestType testType,
384 CompressedTexFormat format)
385 : TestCase(context, name, description)
386 , m_testType(testType)
387 , m_format(format)
388 , m_numBlocksTested(0)
389 , m_currentIteration(0)
390 , m_renderer(new ASTCRenderer2D(context, format, deStringHash(getName())))
391 {
392 DE_ASSERT(!(tcu::isAstcSRGBFormat(m_format) &&
393 tcu::astc::isBlockTestTypeHDROnly(
394 m_testType))); // \note There is no HDR sRGB mode, so these would be redundant.
395 }
396
~ASTCBlockCase2D(void)397 ASTCBlockCase2D::~ASTCBlockCase2D(void)
398 {
399 ASTCBlockCase2D::deinit();
400 }
401
init(void)402 void ASTCBlockCase2D::init(void)
403 {
404 m_renderer->initialize(64, 64, tcu::astc::getBlockTestTypeColorScale(m_testType),
405 tcu::astc::getBlockTestTypeColorBias(m_testType));
406
407 generateBlockCaseTestData(m_blockData, m_format, m_testType);
408 DE_ASSERT(!m_blockData.empty());
409 DE_ASSERT(m_blockData.size() % tcu::astc::BLOCK_SIZE_BYTES == 0);
410
411 m_testCtx.getLog() << TestLog::Message << "Total " << m_blockData.size() / tcu::astc::BLOCK_SIZE_BYTES
412 << " blocks to test" << TestLog::EndMessage << TestLog::Message
413 << "Note: Legitimate ASTC error pixels will be ignored when comparing to reference"
414 << TestLog::EndMessage;
415 }
416
deinit(void)417 void ASTCBlockCase2D::deinit(void)
418 {
419 m_renderer->clear();
420 m_blockData.clear();
421 }
422
iterate(void)423 ASTCBlockCase2D::IterateResult ASTCBlockCase2D::iterate(void)
424 {
425 TestLog &log = m_testCtx.getLog();
426
427 if (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR && tcu::astc::isBlockTestTypeHDROnly(m_testType))
428 {
429 log << TestLog::Message
430 << "Passing the case immediately, since only LDR support was detected and test only contains HDR blocks"
431 << TestLog::EndMessage;
432 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
433 return STOP;
434 }
435
436 const IVec2 blockSize = m_renderer->getBlockSize();
437 const int totalNumBlocks = (int)m_blockData.size() / tcu::astc::BLOCK_SIZE_BYTES;
438 const int numXBlocksPerImage = de::min(m_context.getRenderTarget().getWidth(), 512) / blockSize.x();
439 const int numYBlocksPerImage = de::min(m_context.getRenderTarget().getHeight(), 512) / blockSize.y();
440 const int numBlocksPerImage = numXBlocksPerImage * numYBlocksPerImage;
441 const int imageWidth = numXBlocksPerImage * blockSize.x();
442 const int imageHeight = numYBlocksPerImage * blockSize.y();
443 const int numBlocksRemaining = totalNumBlocks - m_numBlocksTested;
444 const int curNumUsedBlocks = de::min(numBlocksPerImage, numBlocksRemaining);
445 const int curNumUnusedBlocks = numBlocksPerImage - curNumUsedBlocks;
446 const glu::RenderContext &renderCtx = m_context.getRenderContext();
447 const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() +
448 (tcu::isAstcSRGBFormat(m_format) ? tcu::RGBA(2, 2, 2, 2) : tcu::RGBA(1, 1, 1, 1));
449 tcu::CompressedTexture compressed(m_format, imageWidth, imageHeight);
450
451 if (m_currentIteration == 0)
452 {
453 log << TestLog::Message << "Using texture of size " << imageWidth << "x" << imageHeight << ", with "
454 << numXBlocksPerImage << " block columns and " << numYBlocksPerImage << " block rows "
455 << ", with block size " << blockSize.x() << "x" << blockSize.y() << TestLog::EndMessage;
456 }
457
458 DE_ASSERT(compressed.getDataSize() == numBlocksPerImage * tcu::astc::BLOCK_SIZE_BYTES);
459 deMemcpy(compressed.getData(), &m_blockData[m_numBlocksTested * tcu::astc::BLOCK_SIZE_BYTES],
460 curNumUsedBlocks * tcu::astc::BLOCK_SIZE_BYTES);
461 if (curNumUsedBlocks > 1)
462 tcu::astc::generateDefaultVoidExtentBlocks(
463 (uint8_t *)compressed.getData() + curNumUsedBlocks * tcu::astc::BLOCK_SIZE_BYTES, curNumUnusedBlocks);
464
465 // Create texture and render.
466
467 const tcu::TexDecompressionParams::AstcMode decompressionMode =
468 (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format)) ?
469 tcu::TexDecompressionParams::ASTCMODE_LDR :
470 tcu::TexDecompressionParams::ASTCMODE_HDR;
471 glu::Texture2D texture(renderCtx, m_context.getContextInfo(), 1, &compressed,
472 tcu::TexDecompressionParams(decompressionMode));
473 Surface renderedFrame(imageWidth, imageHeight);
474 Surface referenceFrame(imageWidth, imageHeight);
475
476 m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
477
478 // Compare and log.
479 // \note Since a case can draw quite many images, only log the first iteration and failures.
480
481 {
482 Surface errorMask;
483 IVec2 firstFailedBlockCoord;
484 IVec4 maxDiff;
485 const bool compareOk = compareBlockImages(referenceFrame, renderedFrame, threshold, blockSize, curNumUsedBlocks,
486 firstFailedBlockCoord, errorMask, maxDiff);
487
488 if (m_currentIteration == 0 || !compareOk)
489 {
490 const char *const imageSetName = "ComparisonResult";
491 const char *const imageSetDesc = "Comparison Result";
492
493 {
494 tcu::ScopedLogSection section(log, "Iteration " + de::toString(m_currentIteration),
495 "Blocks " + de::toString(m_numBlocksTested) + " to " +
496 de::toString(m_numBlocksTested + curNumUsedBlocks - 1));
497
498 if (curNumUsedBlocks > 0)
499 log << TestLog::Message << "Note: Only the first " << curNumUsedBlocks
500 << " blocks in the image are relevant; rest " << curNumUnusedBlocks
501 << " are dummies and not checked" << TestLog::EndMessage;
502
503 if (!compareOk)
504 {
505 log << TestLog::Message << "Image comparison failed: max difference = " << maxDiff
506 << ", threshold = " << threshold << TestLog::EndMessage
507 << TestLog::ImageSet(imageSetName, imageSetDesc)
508 << TestLog::Image("Result", "Result", renderedFrame)
509 << TestLog::Image("Reference", "Reference", referenceFrame)
510 << TestLog::Image("ErrorMask", "Error mask", errorMask) << TestLog::EndImageSet;
511
512 const int blockNdx =
513 m_numBlocksTested + firstFailedBlockCoord.y() * numXBlocksPerImage + firstFailedBlockCoord.x();
514 DE_ASSERT(blockNdx < totalNumBlocks);
515
516 log << TestLog::Message << "First failed block at column " << firstFailedBlockCoord.x()
517 << " and row " << firstFailedBlockCoord.y() << TestLog::EndMessage << TestLog::Message
518 << "Data of first failed block:\n"
519 << astcBlockDataStr(&m_blockData[blockNdx * tcu::astc::BLOCK_SIZE_BYTES])
520 << TestLog::EndMessage;
521
522 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
523 return STOP;
524 }
525 else
526 {
527 log << TestLog::ImageSet(imageSetName, imageSetDesc)
528 << TestLog::Image("Result", "Result", renderedFrame) << TestLog::EndImageSet;
529 }
530 }
531
532 if (m_numBlocksTested + curNumUsedBlocks < totalNumBlocks)
533 log << TestLog::Message << "Note: not logging further images unless reference comparison fails"
534 << TestLog::EndMessage;
535 }
536 }
537
538 m_currentIteration++;
539 m_numBlocksTested += curNumUsedBlocks;
540
541 if (m_numBlocksTested >= totalNumBlocks)
542 {
543 DE_ASSERT(m_numBlocksTested == totalNumBlocks);
544 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
545 return STOP;
546 }
547
548 return CONTINUE;
549 }
550
ASTCBlockSizeRemainderCase2D(Context & context,const char * name,const char * description,CompressedTexFormat format)551 ASTCBlockSizeRemainderCase2D::ASTCBlockSizeRemainderCase2D(Context &context, const char *name, const char *description,
552 CompressedTexFormat format)
553 : TestCase(context, name, description)
554 , m_format(format)
555 , m_currentIteration(0)
556 , m_renderer(new ASTCRenderer2D(context, format, deStringHash(getName())))
557 {
558 }
559
~ASTCBlockSizeRemainderCase2D(void)560 ASTCBlockSizeRemainderCase2D::~ASTCBlockSizeRemainderCase2D(void)
561 {
562 ASTCBlockSizeRemainderCase2D::deinit();
563 }
564
init(void)565 void ASTCBlockSizeRemainderCase2D::init(void)
566 {
567 const IVec2 blockSize = m_renderer->getBlockSize();
568 m_renderer->initialize(MAX_NUM_BLOCKS_X * blockSize.x(), MAX_NUM_BLOCKS_Y * blockSize.y(), Vec4(1.0f), Vec4(0.0f));
569 }
570
deinit(void)571 void ASTCBlockSizeRemainderCase2D::deinit(void)
572 {
573 m_renderer->clear();
574 }
575
iterate(void)576 ASTCBlockSizeRemainderCase2D::IterateResult ASTCBlockSizeRemainderCase2D::iterate(void)
577 {
578 TestLog &log = m_testCtx.getLog();
579 const IVec2 blockSize = m_renderer->getBlockSize();
580 const int curRemainderX = m_currentIteration % blockSize.x();
581 const int curRemainderY = m_currentIteration / blockSize.x();
582 const int imageWidth = (MAX_NUM_BLOCKS_X - 1) * blockSize.x() + curRemainderX;
583 const int imageHeight = (MAX_NUM_BLOCKS_Y - 1) * blockSize.y() + curRemainderY;
584 const int numBlocksX = deDivRoundUp32(imageWidth, blockSize.x());
585 const int numBlocksY = deDivRoundUp32(imageHeight, blockSize.y());
586 const int totalNumBlocks = numBlocksX * numBlocksY;
587 const glu::RenderContext &renderCtx = m_context.getRenderContext();
588 const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() +
589 (tcu::isAstcSRGBFormat(m_format) ? tcu::RGBA(2, 2, 2, 2) : tcu::RGBA(1, 1, 1, 1));
590 tcu::CompressedTexture compressed(m_format, imageWidth, imageHeight);
591
592 DE_ASSERT(compressed.getDataSize() == totalNumBlocks * tcu::astc::BLOCK_SIZE_BYTES);
593 tcu::astc::generateDefaultNormalBlocks((uint8_t *)compressed.getData(), totalNumBlocks, blockSize.x(),
594 blockSize.y());
595
596 // Create texture and render.
597
598 const tcu::TexDecompressionParams::AstcMode decompressionMode =
599 (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format)) ?
600 tcu::TexDecompressionParams::ASTCMODE_LDR :
601 tcu::TexDecompressionParams::ASTCMODE_HDR;
602 Surface renderedFrame(imageWidth, imageHeight);
603 Surface referenceFrame(imageWidth, imageHeight);
604 glu::Texture2D texture(renderCtx, m_context.getContextInfo(), 1, &compressed,
605 tcu::TexDecompressionParams(decompressionMode));
606
607 m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
608
609 {
610 // Compare and log.
611
612 tcu::ScopedLogSection section(log, "Iteration " + de::toString(m_currentIteration),
613 "Remainder " + de::toString(curRemainderX) + "x" + de::toString(curRemainderY));
614
615 log << TestLog::Message << "Using texture of size " << imageWidth << "x" << imageHeight << " and block size "
616 << blockSize.x() << "x" << blockSize.y() << "; the x and y remainders are " << curRemainderX << " and "
617 << curRemainderY << " respectively" << TestLog::EndMessage;
618
619 const bool compareOk = tcu::pixelThresholdCompare(
620 m_testCtx.getLog(), "ComparisonResult", "Comparison Result", referenceFrame, renderedFrame, threshold,
621 m_currentIteration == 0 ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
622
623 if (!compareOk)
624 {
625 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
626 return STOP;
627 }
628 }
629
630 if (m_currentIteration == 0 && m_currentIteration + 1 < blockSize.x() * blockSize.y())
631 log << TestLog::Message << "Note: not logging further images unless reference comparison fails"
632 << TestLog::EndMessage;
633
634 m_currentIteration++;
635
636 if (m_currentIteration >= blockSize.x() * blockSize.y())
637 {
638 DE_ASSERT(m_currentIteration == blockSize.x() * blockSize.y());
639 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
640 return STOP;
641 }
642 return CONTINUE;
643 }
644
645 } // namespace Functional
646 } // namespace gles3
647 } // namespace deqp
648