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