xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fTextureBorderClampTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2015 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 Texture border clamp tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fTextureBorderClampTests.hpp"
25 
26 #include "glsTextureTestUtil.hpp"
27 
28 #include "tcuTextureUtil.hpp"
29 #include "tcuTexLookupVerifier.hpp"
30 #include "tcuTexCompareVerifier.hpp"
31 #include "tcuCompressedTexture.hpp"
32 #include "tcuResultCollector.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuSeedBuilder.hpp"
35 #include "tcuVectorUtil.hpp"
36 
37 #include "rrGenericVector.hpp"
38 
39 #include "gluContextInfo.hpp"
40 #include "gluTexture.hpp"
41 #include "gluTextureUtil.hpp"
42 #include "gluPixelTransfer.hpp"
43 #include "gluStrUtil.hpp"
44 #include "gluObjectWrapper.hpp"
45 #include "gluShaderProgram.hpp"
46 #include "gluDrawUtil.hpp"
47 
48 #include "glwEnums.hpp"
49 #include "glwFunctions.hpp"
50 
51 #include "deStringUtil.hpp"
52 #include "deUniquePtr.hpp"
53 #include "deRandom.hpp"
54 
55 #include <limits>
56 
57 namespace deqp
58 {
59 namespace gles31
60 {
61 namespace Functional
62 {
63 namespace
64 {
65 
66 enum SizeType
67 {
68     SIZE_POT = 0,
69     SIZE_NPOT
70 };
71 
filterRequiresFilterability(uint32_t filter)72 bool filterRequiresFilterability(uint32_t filter)
73 {
74     switch (filter)
75     {
76     case GL_NEAREST:
77     case GL_NEAREST_MIPMAP_NEAREST:
78         return false;
79 
80     case GL_LINEAR:
81     case GL_LINEAR_MIPMAP_NEAREST:
82     case GL_NEAREST_MIPMAP_LINEAR:
83     case GL_LINEAR_MIPMAP_LINEAR:
84         return true;
85 
86     default:
87         DE_ASSERT(false);
88         return false;
89     }
90 }
91 
isDepthFormat(uint32_t format,tcu::Sampler::DepthStencilMode mode)92 bool isDepthFormat(uint32_t format, tcu::Sampler::DepthStencilMode mode)
93 {
94     if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA)
95     {
96         // Unsized formats are a special case
97         return false;
98     }
99     else if (glu::isCompressedFormat(format))
100     {
101         // no known compressed depth formats
102         return false;
103     }
104     else
105     {
106         const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format);
107 
108         if (fmt.order == tcu::TextureFormat::D)
109         {
110             DE_ASSERT(mode == tcu::Sampler::MODE_DEPTH);
111             return true;
112         }
113         else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_DEPTH)
114             return true;
115         else
116             return false;
117     }
118 }
119 
isStencilFormat(uint32_t format,tcu::Sampler::DepthStencilMode mode)120 bool isStencilFormat(uint32_t format, tcu::Sampler::DepthStencilMode mode)
121 {
122     if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA)
123     {
124         // Unsized formats are a special case
125         return false;
126     }
127     else if (glu::isCompressedFormat(format))
128     {
129         // no known compressed stencil formats
130         return false;
131     }
132     else
133     {
134         const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format);
135 
136         if (fmt.order == tcu::TextureFormat::S)
137         {
138             DE_ASSERT(mode == tcu::Sampler::MODE_STENCIL);
139             return true;
140         }
141         else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_STENCIL)
142             return true;
143         else
144             return false;
145     }
146 }
147 
getFormatChannelClass(uint32_t format,tcu::Sampler::DepthStencilMode mode)148 tcu::TextureChannelClass getFormatChannelClass(uint32_t format, tcu::Sampler::DepthStencilMode mode)
149 {
150     if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA)
151     {
152         // Unsized formats are a special c, use UNORM8
153         return tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
154     }
155     else if (glu::isCompressedFormat(format))
156     {
157         const tcu::CompressedTexFormat compressedFmt = glu::mapGLCompressedTexFormat(format);
158         const tcu::TextureFormat uncompressedFmt     = tcu::getUncompressedFormat(compressedFmt);
159         return tcu::getTextureChannelClass(uncompressedFmt.type);
160     }
161     else
162     {
163         const tcu::TextureFormat fmt          = glu::mapGLInternalFormat(format);
164         const tcu::TextureFormat effectiveFmt = tcu::getEffectiveDepthStencilTextureFormat(fmt, mode);
165 
166         return tcu::getTextureChannelClass(effectiveFmt.type);
167     }
168 }
169 
getDimensionNumBlocks(int dimensionSize,int blockSize)170 int getDimensionNumBlocks(int dimensionSize, int blockSize)
171 {
172     // ceil( a / b )
173     return (dimensionSize + blockSize - 1) / blockSize;
174 }
175 
generateDefaultCompressedData(tcu::CompressedTexture & dst,const tcu::CompressedTexFormat & format)176 void generateDefaultCompressedData(tcu::CompressedTexture &dst, const tcu::CompressedTexFormat &format)
177 {
178     const int blockByteSize         = tcu::getBlockSize(format);
179     const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(format);
180     const tcu::IVec3 numBlocks(getDimensionNumBlocks(dst.getWidth(), blockPixelSize.x()),
181                                getDimensionNumBlocks(dst.getHeight(), blockPixelSize.y()),
182                                getDimensionNumBlocks(dst.getDepth(), blockPixelSize.z()));
183     const int numTotalBlocks = numBlocks.x() * numBlocks.y() * numBlocks.z();
184     const int dataSize       = numTotalBlocks * blockByteSize;
185 
186     DE_ASSERT(dst.getDataSize() == dataSize);
187 
188     if (tcu::isAstcFormat(format))
189     {
190         // generate data that is valid in LDR mode
191         const int BLOCK_SIZE            = 16;
192         const uint8_t block[BLOCK_SIZE] = {252, 253, 255, 255, 255, 255, 255, 255,
193                                            223, 251, 28,  206, 54,  251, 160, 174};
194 
195         DE_ASSERT(blockByteSize == BLOCK_SIZE);
196         for (int ndx = 0; ndx < numTotalBlocks; ++ndx)
197             deMemcpy((uint8_t *)dst.getData() + ndx * BLOCK_SIZE, block, BLOCK_SIZE);
198     }
199     else
200     {
201         // any data is ok
202         de::Random rnd(0xabc);
203 
204         for (int ndx = 0; ndx < dataSize; ++ndx)
205             ((uint8_t *)dst.getData())[ndx] = rnd.getUint8();
206     }
207 }
208 
209 template <typename T>
210 struct TextureTraits
211 {
212 };
213 
214 template <>
215 struct TextureTraits<glu::Texture2D>
216 {
217     typedef tcu::IVec2 SizeType;
218 
createTextureFromInternalFormatdeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits219     static de::MovePtr<glu::Texture2D> createTextureFromInternalFormat(glu::RenderContext &renderCtx,
220                                                                        uint32_t texFormat, const tcu::IVec2 &size)
221     {
222         return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, size.x(), size.y()));
223     }
224 
createTextureFromFormatAndTypedeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits225     static de::MovePtr<glu::Texture2D> createTextureFromFormatAndType(glu::RenderContext &renderCtx, uint32_t texFormat,
226                                                                       uint32_t type, const tcu::IVec2 &size)
227     {
228         return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, type, size.x(), size.y()));
229     }
230 
createTextureFromCompressedDatadeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits231     static de::MovePtr<glu::Texture2D> createTextureFromCompressedData(
232         glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo, const tcu::CompressedTexture &compressedLevel,
233         const tcu::TexDecompressionParams &decompressionParams)
234     {
235         return de::MovePtr<glu::Texture2D>(
236             new glu::Texture2D(renderCtx, ctxInfo, 1, &compressedLevel, decompressionParams));
237     }
238 
getTextureNumLayersdeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits239     static int getTextureNumLayers(const tcu::IVec2 &size)
240     {
241         // 2D textures have one layer
242         DE_UNREF(size);
243         return 1;
244     }
245 };
246 
247 template <>
248 struct TextureTraits<glu::Texture3D>
249 {
250     typedef tcu::IVec3 SizeType;
251 
createTextureFromInternalFormatdeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits252     static de::MovePtr<glu::Texture3D> createTextureFromInternalFormat(glu::RenderContext &renderCtx,
253                                                                        uint32_t texFormat, const tcu::IVec3 &size)
254     {
255         return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, texFormat, size.x(), size.y(), size.z()));
256     }
257 
createTextureFromFormatAndTypedeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits258     static de::MovePtr<glu::Texture3D> createTextureFromFormatAndType(glu::RenderContext &renderCtx, uint32_t texFormat,
259                                                                       uint32_t type, const tcu::IVec3 &size)
260     {
261         return de::MovePtr<glu::Texture3D>(
262             new glu::Texture3D(renderCtx, texFormat, type, size.x(), size.y(), size.z()));
263     }
264 
createTextureFromCompressedDatadeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits265     static de::MovePtr<glu::Texture3D> createTextureFromCompressedData(
266         glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo, const tcu::CompressedTexture &compressedLevel,
267         const tcu::TexDecompressionParams &decompressionParams)
268     {
269         return de::MovePtr<glu::Texture3D>(
270             new glu::Texture3D(renderCtx, ctxInfo, 1, &compressedLevel, decompressionParams));
271     }
272 
getTextureNumLayersdeqp::gles31::Functional::__anon3e6ef60a0111::TextureTraits273     static int getTextureNumLayers(const tcu::IVec3 &size)
274     {
275         // 3D textures have Z layers
276         return size.z();
277     }
278 };
279 
280 template <typename T>
genDefaultTexture(glu::RenderContext & renderCtx,const glu::ContextInfo & ctxInfo,uint32_t texFormat,const typename TextureTraits<T>::SizeType & size)281 de::MovePtr<T> genDefaultTexture(glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo, uint32_t texFormat,
282                                  const typename TextureTraits<T>::SizeType &size)
283 {
284     de::MovePtr<T> texture;
285 
286     if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH) || isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL))
287     {
288         // fill different channels with different gradients
289         texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size);
290         texture->getRefTexture().allocLevel(0);
291 
292         if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH))
293         {
294             // fill depth with 0 -> 1
295             const tcu::PixelBufferAccess depthAccess =
296                 tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_DEPTH);
297             tcu::fillWithComponentGradients(depthAccess, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
298         }
299 
300         if (isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL))
301         {
302             // fill stencil with 0 -> max
303             const tcu::PixelBufferAccess stencilAccess =
304                 tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_STENCIL);
305             const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(stencilAccess.getFormat());
306 
307             // Flip y to make stencil and depth cases not look identical
308             tcu::fillWithComponentGradients(tcu::flipYAccess(stencilAccess), texFormatInfo.valueMax,
309                                             texFormatInfo.valueMin);
310         }
311 
312         texture->upload();
313     }
314     else if (!glu::isCompressedFormat(texFormat))
315     {
316         if (texFormat == GL_LUMINANCE || texFormat == GL_LUMINANCE_ALPHA || texFormat == GL_ALPHA ||
317             texFormat == GL_BGRA)
318             texture = TextureTraits<T>::createTextureFromFormatAndType(renderCtx, texFormat, GL_UNSIGNED_BYTE, size);
319         else
320             texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size);
321 
322         // Fill level 0.
323         texture->getRefTexture().allocLevel(0);
324 
325         // fill with gradient min -> max
326         {
327             const tcu::TextureFormatInfo texFormatInfo =
328                 tcu::getTextureFormatInfo(texture->getRefTexture().getFormat());
329             const tcu::Vec4 rampLow  = texFormatInfo.valueMin;
330             const tcu::Vec4 rampHigh = texFormatInfo.valueMax;
331             tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(0), rampLow, rampHigh);
332         }
333 
334         texture->upload();
335     }
336     else
337     {
338         const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(texFormat);
339         const int numLayers                             = TextureTraits<T>::getTextureNumLayers(size);
340         tcu::CompressedTexture compressedLevel(compressedFormat, size.x(), size.y(), numLayers);
341         const bool isAstcFormat = tcu::isAstcFormat(compressedFormat);
342         tcu::TexDecompressionParams decompressionParams((isAstcFormat) ? (tcu::TexDecompressionParams::ASTCMODE_LDR) :
343                                                                          (tcu::TexDecompressionParams::ASTCMODE_LAST));
344 
345         generateDefaultCompressedData(compressedLevel, compressedFormat);
346 
347         texture =
348             TextureTraits<T>::createTextureFromCompressedData(renderCtx, ctxInfo, compressedLevel, decompressionParams);
349     }
350 
351     return texture;
352 }
353 
getNBitIntegerMaxValue(bool isSigned,int numBits)354 int getNBitIntegerMaxValue(bool isSigned, int numBits)
355 {
356     DE_ASSERT(numBits < 32);
357 
358     if (numBits == 0)
359         return 0;
360     else if (isSigned)
361         return deIntMaxValue32(numBits);
362     else
363         return deUintMaxValue32(numBits);
364 }
365 
getNBitIntegerMinValue(bool isSigned,int numBits)366 int getNBitIntegerMinValue(bool isSigned, int numBits)
367 {
368     DE_ASSERT(numBits < 32);
369 
370     if (numBits == 0)
371         return 0;
372     else if (isSigned)
373         return deIntMinValue32(numBits);
374     else
375         return 0;
376 }
377 
getNBitIntegerVec4MaxValue(bool isSigned,const tcu::IVec4 & numBits)378 tcu::IVec4 getNBitIntegerVec4MaxValue(bool isSigned, const tcu::IVec4 &numBits)
379 {
380     return tcu::IVec4(getNBitIntegerMaxValue(isSigned, numBits[0]), getNBitIntegerMaxValue(isSigned, numBits[1]),
381                       getNBitIntegerMaxValue(isSigned, numBits[2]), getNBitIntegerMaxValue(isSigned, numBits[3]));
382 }
383 
getNBitIntegerVec4MinValue(bool isSigned,const tcu::IVec4 & numBits)384 tcu::IVec4 getNBitIntegerVec4MinValue(bool isSigned, const tcu::IVec4 &numBits)
385 {
386     return tcu::IVec4(getNBitIntegerMinValue(isSigned, numBits[0]), getNBitIntegerMinValue(isSigned, numBits[1]),
387                       getNBitIntegerMinValue(isSigned, numBits[2]), getNBitIntegerMinValue(isSigned, numBits[3]));
388 }
389 
mapToFormatColorUnits(const tcu::TextureFormat & texFormat,const tcu::Vec4 & normalizedRange)390 rr::GenericVec4 mapToFormatColorUnits(const tcu::TextureFormat &texFormat, const tcu::Vec4 &normalizedRange)
391 {
392     const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat);
393 
394     switch (tcu::getTextureChannelClass(texFormat.type))
395     {
396     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
397         return rr::GenericVec4(normalizedRange);
398     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
399         return rr::GenericVec4(normalizedRange * 2.0f - 1.0f);
400     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
401         return rr::GenericVec4(texFormatInfo.valueMin + normalizedRange * texFormatInfo.valueMax);
402     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
403         return rr::GenericVec4(
404             tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<int32_t>());
405     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
406         return rr::GenericVec4(
407             tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<uint32_t>());
408 
409     default:
410         DE_ASSERT(false);
411         return rr::GenericVec4();
412     }
413 }
414 
mapToFormatColorRepresentable(const tcu::TextureFormat & texFormat,const tcu::Vec4 & normalizedRange)415 rr::GenericVec4 mapToFormatColorRepresentable(const tcu::TextureFormat &texFormat, const tcu::Vec4 &normalizedRange)
416 {
417     // make sure value is representable in the target format and clear channels
418     // not present in the target format.
419 
420     const rr::GenericVec4 inFormatUnits = mapToFormatColorUnits(texFormat, normalizedRange);
421     const tcu::BVec4 channelMask        = tcu::getTextureFormatChannelMask(texFormat);
422     de::ArrayBuffer<uint8_t, 4> buffer(texFormat.getPixelSize());
423     tcu::PixelBufferAccess access(texFormat, tcu::IVec3(1, 1, 1), buffer.getPtr());
424 
425     if (tcu::isSRGB(texFormat))
426     {
427         DE_ASSERT(texFormat.type == tcu::TextureFormat::UNORM_INT8);
428 
429         // make sure border color (in linear space) can be converted to 8-bit sRGB space without
430         // significant loss.
431         const tcu::Vec4 sRGB   = tcu::linearToSRGB(normalizedRange);
432         const tcu::IVec4 sRGB8 = tcu::IVec4(tcu::floatToU8(sRGB[0]), tcu::floatToU8(sRGB[1]), tcu::floatToU8(sRGB[2]),
433                                             tcu::floatToU8(sRGB[3]));
434         const tcu::Vec4 linearized = tcu::sRGBToLinear(tcu::Vec4((float)sRGB8[0] / 255.0f, (float)sRGB8[1] / 255.0f,
435                                                                  (float)sRGB8[2] / 255.0f, (float)sRGB8[3] / 255.0f));
436 
437         return rr::GenericVec4(tcu::select(linearized, tcu::Vec4(0.0f), channelMask));
438     }
439 
440     switch (tcu::getTextureChannelClass(texFormat.type))
441     {
442     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
443     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
444     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
445     {
446         access.setPixel(inFormatUnits.get<float>(), 0, 0);
447         return rr::GenericVec4(tcu::select(access.getPixel(0, 0), tcu::Vec4(0.0f), channelMask));
448     }
449     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
450     {
451         access.setPixel(inFormatUnits.get<int32_t>(), 0, 0);
452         return rr::GenericVec4(tcu::select(access.getPixelInt(0, 0), tcu::IVec4(0), channelMask));
453     }
454     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
455     {
456         access.setPixel(inFormatUnits.get<uint32_t>(), 0, 0);
457         return rr::GenericVec4(tcu::select(access.getPixelUint(0, 0), tcu::UVec4(0u), channelMask));
458     }
459     default:
460     {
461         DE_ASSERT(false);
462         return rr::GenericVec4();
463     }
464     }
465 }
466 
isCoreFilterableFormat(uint32_t format,tcu::Sampler::DepthStencilMode mode,bool is_texture_float_linear_supported=true)467 bool isCoreFilterableFormat(uint32_t format, tcu::Sampler::DepthStencilMode mode,
468                             bool is_texture_float_linear_supported = true)
469 {
470     const bool isLuminanceOrAlpha   = (format == GL_LUMINANCE || format == GL_ALPHA ||
471                                      format == GL_LUMINANCE_ALPHA); // special case for luminance/alpha
472     const bool isUnsizedColorFormat = (format == GL_BGRA);
473     const bool isCompressed         = glu::isCompressedFormat(format);
474     const bool isDepth              = isDepthFormat(format, mode);
475     const bool isStencil            = isStencilFormat(format, mode);
476     const bool isFP32Format = (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F || format == GL_R32F);
477 
478     // special cases
479     if (isLuminanceOrAlpha || isUnsizedColorFormat || isCompressed)
480         return true;
481     if (isStencil || isDepth)
482         return false;
483     if (isFP32Format)
484         return is_texture_float_linear_supported;
485 
486     // color case
487     return glu::isGLInternalColorFormatFilterable(format);
488 }
489 
490 class TextureBorderClampTest : public TestCase
491 {
492 public:
493     enum StateType
494     {
495         STATE_SAMPLER_PARAM = 0,
496         STATE_TEXTURE_PARAM,
497 
498         STATE_LAST
499     };
500 
501     enum SamplingFunction
502     {
503         SAMPLE_FILTER = 0,
504         SAMPLE_GATHER,
505 
506         SAMPLE_LAST
507     };
508 
509     enum Flag
510     {
511         FLAG_USE_SHADOW_SAMPLER    = (1u << 0),
512         FLAG_TEST_FLOAT_FILTERABLE = (1u << 1),
513     };
514 
515     struct IterationConfig
516     {
517         tcu::Vec2 p0;
518         tcu::Vec2 p1;
519         rr::GenericVec4 borderColor;
520         tcu::Vec4 lookupScale;
521         tcu::Vec4 lookupBias;
522         uint32_t minFilter;
523         uint32_t magFilter;
524         std::string description;
525         uint32_t sWrapMode;
526         uint32_t tWrapMode;
527         uint32_t compareMode;
528         float compareRef;
529     };
530 
531     TextureBorderClampTest(Context &context, const char *name, const char *description, uint32_t texFormat,
532                            tcu::Sampler::DepthStencilMode mode, StateType stateType, int texWidth, int texHeight,
533                            SamplingFunction samplingFunction, uint32_t filter, uint32_t flags = 0);
534     ~TextureBorderClampTest(void);
535 
536 protected:
537     void init(void);
538     void deinit(void);
539 
540 private:
541     IterateResult iterate(void);
542 
543     void logParams(const IterationConfig &config, const glu::TextureTestUtil::ReferenceParams &samplerParams);
544 
545     void renderTo(tcu::Surface &surface, const IterationConfig &config,
546                   const glu::TextureTestUtil::ReferenceParams &samplerParams);
547     void renderQuad(const float *texCoord, const glu::TextureTestUtil::ReferenceParams &samplerParams);
548 
549     void verifyImage(const tcu::Surface &image, const IterationConfig &config,
550                      const glu::TextureTestUtil::ReferenceParams &samplerParams);
551 
552     bool verifyTextureSampleResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord,
553                                    const glu::TextureTestUtil::ReferenceParams &samplerParams,
554                                    const tcu::LodPrecision &lodPrecision, const tcu::LookupPrecision &lookupPrecision);
555 
556     bool verifyTextureCompareResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord,
557                                     const glu::TextureTestUtil::ReferenceParams &samplerParams,
558                                     const tcu::TexComparePrecision &texComparePrecision,
559                                     const tcu::TexComparePrecision &lowQualityTexComparePrecision,
560                                     const tcu::LodPrecision &lodPrecision,
561                                     const tcu::LodPrecision &lowQualityLodPrecision);
562 
563     bool verifyTextureGatherResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord,
564                                    const glu::TextureTestUtil::ReferenceParams &samplerParams,
565                                    const tcu::LookupPrecision &lookupPrecision);
566 
567     bool verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess &renderedFrame, const float *texCoord,
568                                       const glu::TextureTestUtil::ReferenceParams &samplerParams,
569                                       const tcu::TexComparePrecision &texComparePrecision,
570                                       const tcu::TexComparePrecision &lowQualityTexComparePrecision);
571 
572     uint32_t getIterationSeed(const IterationConfig &config) const;
573     glu::TextureTestUtil::ReferenceParams genSamplerParams(const IterationConfig &config) const;
574     glu::ShaderProgram *genGatherProgram(void) const;
575 
576     virtual int getNumIterations(void) const            = 0;
577     virtual IterationConfig getIteration(int ndx) const = 0;
578 
579 protected:
580     const glu::Texture2D *getTexture(void) const;
581 
582     const uint32_t m_texFormat;
583     const tcu::Sampler::DepthStencilMode m_sampleMode;
584     const tcu::TextureChannelClass m_channelClass;
585     const StateType m_stateType;
586 
587     const int m_texHeight;
588     const int m_texWidth;
589 
590     const SamplingFunction m_samplingFunction;
591     const bool m_useShadowSampler;
592     const bool m_useFloatFilterable;
593 
594     const uint32_t m_filter;
595 
596 private:
597     enum
598     {
599         VIEWPORT_WIDTH  = 128,
600         VIEWPORT_HEIGHT = 128,
601     };
602 
603     de::MovePtr<glu::Texture2D> m_texture;
604     de::MovePtr<gls::TextureTestUtil::TextureRenderer> m_renderer;
605     de::MovePtr<glu::ShaderProgram> m_gatherProgram;
606 
607     int m_iterationNdx;
608     tcu::ResultCollector m_result;
609 };
610 
TextureBorderClampTest(Context & context,const char * name,const char * description,uint32_t texFormat,tcu::Sampler::DepthStencilMode mode,StateType stateType,int texWidth,int texHeight,SamplingFunction samplingFunction,uint32_t filter,uint32_t flags)611 TextureBorderClampTest::TextureBorderClampTest(Context &context, const char *name, const char *description,
612                                                uint32_t texFormat, tcu::Sampler::DepthStencilMode mode,
613                                                StateType stateType, int texWidth, int texHeight,
614                                                SamplingFunction samplingFunction, uint32_t filter, uint32_t flags)
615     : TestCase(context, name, description)
616     , m_texFormat(texFormat)
617     , m_sampleMode(mode)
618     , m_channelClass(getFormatChannelClass(texFormat, mode))
619     , m_stateType(stateType)
620     , m_texHeight(texHeight)
621     , m_texWidth(texWidth)
622     , m_samplingFunction(samplingFunction)
623     , m_useShadowSampler((flags & FLAG_USE_SHADOW_SAMPLER) != 0)
624     , m_useFloatFilterable((flags & FLAG_TEST_FLOAT_FILTERABLE) != 0)
625     , m_filter(filter)
626     , m_iterationNdx(0)
627     , m_result(context.getTestContext().getLog())
628 {
629     DE_ASSERT(stateType < STATE_LAST);
630     DE_ASSERT(samplingFunction < SAMPLE_LAST);
631     // mode must be set for combined depth-stencil formats
632     DE_ASSERT(m_channelClass != tcu::TEXTURECHANNELCLASS_LAST || mode != tcu::Sampler::MODE_LAST);
633 }
634 
~TextureBorderClampTest(void)635 TextureBorderClampTest::~TextureBorderClampTest(void)
636 {
637     deinit();
638 }
639 
init(void)640 void TextureBorderClampTest::init(void)
641 {
642     // requirements
643     const bool supportsGL45 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5));
644     const bool supportsES32orGL45 =
645         glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) || supportsGL45;
646 
647     // repeat filterable test with valid context
648     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
649     const bool is_texture_float_linear_supported =
650         glu::hasExtension(gl, glu::ApiType::es(3, 0), "GL_OES_texture_float_linear");
651     const bool coreFilterable = isCoreFilterableFormat(m_texFormat, m_sampleMode, is_texture_float_linear_supported);
652 
653     if (m_useFloatFilterable && !coreFilterable && filterRequiresFilterability(m_filter))
654         throw tcu::NotSupportedError("Test requires GL_OES_texture_float_linear extension");
655 
656     if (!supportsES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp"))
657         throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension");
658 
659     if (glu::isCompressedFormat(m_texFormat) && !supportsES32orGL45 &&
660         tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat)) &&
661         !m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
662     {
663         throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension");
664     }
665 
666     if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888"))
667         throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension");
668 
669     if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH ||
670         m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT)
671     {
672         throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" +
673                                      de::toString<int>(VIEWPORT_HEIGHT) + " viewport");
674     }
675 
676     // resources
677 
678     m_texture = genDefaultTexture<glu::Texture2D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat,
679                                                   tcu::IVec2(m_texWidth, m_texHeight));
680 
681     m_testCtx.getLog() << tcu::TestLog::Message << "Created texture with format "
682                        << glu::getTextureFormatName(m_texFormat) << ", size (" << m_texture->getRefTexture().getWidth()
683                        << ", " << m_texture->getRefTexture().getHeight() << ")\n"
684                        << "Setting sampling state using "
685                        << ((m_stateType == STATE_TEXTURE_PARAM) ? ("texture state") : ("sampler state"))
686                        << tcu::TestLog::EndMessage;
687 
688     if (m_samplingFunction == SAMPLE_FILTER)
689     {
690         const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
691 
692         m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(
693             m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP));
694     }
695     else
696     {
697         m_gatherProgram = de::MovePtr<glu::ShaderProgram>(genGatherProgram());
698 
699         m_testCtx.getLog() << tcu::TestLog::Message << "Using texture gather to sample texture"
700                            << tcu::TestLog::EndMessage << *m_gatherProgram;
701 
702         if (!m_gatherProgram->isOk())
703             throw tcu::TestError("failed to build program");
704     }
705 }
706 
deinit(void)707 void TextureBorderClampTest::deinit(void)
708 {
709     m_texture.clear();
710     m_renderer.clear();
711     m_gatherProgram.clear();
712 }
713 
iterate(void)714 TextureBorderClampTest::IterateResult TextureBorderClampTest::iterate(void)
715 {
716     const IterationConfig iterationConfig = getIteration(m_iterationNdx);
717     const std::string iterationDesc =
718         "Iteration " + de::toString(m_iterationNdx + 1) +
719         (iterationConfig.description.empty() ? ("") : (" - " + iterationConfig.description));
720     const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", iterationDesc);
721     tcu::Surface renderedFrame(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
722     const glu::TextureTestUtil::ReferenceParams samplerParams = genSamplerParams(iterationConfig);
723 
724     logParams(iterationConfig, samplerParams);
725     renderTo(renderedFrame, iterationConfig, samplerParams);
726     verifyImage(renderedFrame, iterationConfig, samplerParams);
727 
728     if (++m_iterationNdx == getNumIterations())
729     {
730         m_result.setTestContextResult(m_testCtx);
731         return STOP;
732     }
733     return CONTINUE;
734 }
735 
logParams(const IterationConfig & config,const glu::TextureTestUtil::ReferenceParams & samplerParams)736 void TextureBorderClampTest::logParams(const IterationConfig &config,
737                                        const glu::TextureTestUtil::ReferenceParams &samplerParams)
738 {
739     const std::string borderColorString = (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ?
740                                               (de::toString(config.borderColor.get<int32_t>())) :
741                                           (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ?
742                                               (de::toString(config.borderColor.get<uint32_t>())) :
743                                               (de::toString(config.borderColor.get<float>()));
744 
745     m_testCtx.getLog() << tcu::TestLog::Message << "Rendering full screen quad, tex coords bottom-left: " << config.p0
746                        << ", top-right " << config.p1 << "\n"
747                        << "Border color is " << borderColorString << "\n"
748                        << "Texture lookup bias: " << samplerParams.colorBias << "\n"
749                        << "Texture lookup scale: " << samplerParams.colorScale << "\n"
750                        << "Filters: min = "
751                        << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.minFilter))
752                        << ", mag = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.magFilter))
753                        << "\n"
754                        << "Wrap mode: s = " << glu::getRepeatModeStr(config.sWrapMode)
755                        << ", t = " << glu::getRepeatModeStr(config.tWrapMode) << "\n"
756                        << tcu::TestLog::EndMessage;
757 
758     if (m_sampleMode == tcu::Sampler::MODE_DEPTH)
759         m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is DEPTH_COMPONENT"
760                            << tcu::TestLog::EndMessage;
761     else if (m_sampleMode == tcu::Sampler::MODE_STENCIL)
762         m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is STENCIL_INDEX"
763                            << tcu::TestLog::EndMessage;
764 
765     if (config.compareMode != GL_NONE)
766     {
767         m_testCtx.getLog() << tcu::TestLog::Message << "Texture mode is COMPARE_REF_TO_TEXTURE, mode = "
768                            << glu::getCompareFuncStr(config.compareMode) << "\n"
769                            << "Compare reference value = " << config.compareRef << "\n"
770                            << tcu::TestLog::EndMessage;
771     }
772 }
773 
renderTo(tcu::Surface & surface,const IterationConfig & config,const glu::TextureTestUtil::ReferenceParams & samplerParams)774 void TextureBorderClampTest::renderTo(tcu::Surface &surface, const IterationConfig &config,
775                                       const glu::TextureTestUtil::ReferenceParams &samplerParams)
776 {
777     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
778     const gls::TextureTestUtil::RandomViewport viewport(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT,
779                                                         getIterationSeed(config));
780     std::vector<float> texCoord;
781     de::MovePtr<glu::Sampler> sampler;
782 
783     glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1);
784 
785     // Bind to unit 0.
786     gl.activeTexture(GL_TEXTURE0);
787     gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
788 
789     if (m_sampleMode == tcu::Sampler::MODE_DEPTH)
790         gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
791     else if (m_sampleMode == tcu::Sampler::MODE_STENCIL)
792         gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
793 
794     if (config.compareMode == GL_NONE)
795     {
796         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
797         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS);
798     }
799     else
800     {
801         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
802         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, config.compareMode);
803     }
804 
805     if (m_stateType == STATE_TEXTURE_PARAM)
806     {
807         // Setup filtering and wrap modes.
808         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS));
809         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT));
810         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter));
811         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter));
812 
813         switch (m_channelClass)
814         {
815         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
816         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
817         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
818             gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>());
819             break;
820 
821         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
822             gl.texParameterIiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<int32_t>());
823             break;
824 
825         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
826             gl.texParameterIuiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<uint32_t>());
827             break;
828 
829         default:
830             DE_ASSERT(false);
831         }
832     }
833     else if (m_stateType == STATE_SAMPLER_PARAM)
834     {
835         const tcu::Vec4 blue(0.0f, 0.0f, 1.0f, 1.0f);
836 
837         // Setup filtering and wrap modes to bad values
838         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
839         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
840         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
841         gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
842         gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blue.getPtr()); // just set some unlikely color
843 
844         // setup sampler to correct values
845         sampler = de::MovePtr<glu::Sampler>(new glu::Sampler(m_context.getRenderContext()));
846 
847         gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS));
848         gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT));
849         gl.samplerParameteri(**sampler, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter));
850         gl.samplerParameteri(**sampler, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter));
851 
852         switch (m_channelClass)
853         {
854         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
855         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
856         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
857             gl.samplerParameterfv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>());
858             break;
859 
860         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
861             gl.samplerParameterIiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<int32_t>());
862             break;
863 
864         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
865             gl.samplerParameterIuiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<uint32_t>());
866             break;
867 
868         default:
869             DE_ASSERT(false);
870         }
871 
872         gl.bindSampler(0, **sampler);
873     }
874 
875     GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
876 
877     gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
878     renderQuad(&texCoord[0], samplerParams);
879     glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess());
880 }
881 
renderQuad(const float * texCoord,const glu::TextureTestUtil::ReferenceParams & samplerParams)882 void TextureBorderClampTest::renderQuad(const float *texCoord,
883                                         const glu::TextureTestUtil::ReferenceParams &samplerParams)
884 {
885     // use TextureRenderer for basic rendering, use custom for gather
886     if (m_samplingFunction == SAMPLE_FILTER)
887         m_renderer->renderQuad(0, texCoord, samplerParams);
888     else
889     {
890         static const float position[]                = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, +1.0f, 0.0f, 1.0f,
891                                                         +1.0f, -1.0f, 0.0f, 1.0f, +1.0f, +1.0f, 0.0f, 1.0f};
892         static const uint16_t indices[]              = {0, 1, 2, 2, 1, 3};
893         const glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("a_position", 4, 4, 0, &position[0]),
894                                                         glu::va::Float("a_texcoord", 2, 4, 0, texCoord)};
895 
896         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
897         const uint32_t progId    = m_gatherProgram->getProgram();
898 
899         gl.useProgram(progId);
900         gl.uniform1i(gl.getUniformLocation(progId, "u_sampler"), 0);
901         if (m_useShadowSampler)
902             gl.uniform1f(gl.getUniformLocation(progId, "u_ref"), samplerParams.ref);
903         gl.uniform4fv(gl.getUniformLocation(progId, "u_colorScale"), 1, samplerParams.colorScale.getPtr());
904         gl.uniform4fv(gl.getUniformLocation(progId, "u_colorBias"), 1, samplerParams.colorBias.getPtr());
905 
906         glu::draw(m_context.getRenderContext(), progId, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
907                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
908     }
909 }
910 
verifyImage(const tcu::Surface & renderedFrame,const IterationConfig & config,const glu::TextureTestUtil::ReferenceParams & samplerParams)911 void TextureBorderClampTest::verifyImage(const tcu::Surface &renderedFrame, const IterationConfig &config,
912                                          const glu::TextureTestUtil::ReferenceParams &samplerParams)
913 {
914     const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
915 
916     tcu::LodPrecision lodPrecision;
917     std::vector<float> texCoord;
918     bool verificationOk;
919 
920     glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1);
921 
922     lodPrecision.derivateBits = 18;
923     lodPrecision.lodBits      = 5;
924 
925     if (samplerParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE)
926     {
927         const tcu::TextureFormat texFormat =
928             tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode);
929         const bool isNearestMinFilter = samplerParams.sampler.minFilter == tcu::Sampler::NEAREST ||
930                                         samplerParams.sampler.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST;
931         const bool isNearestMagFilter = samplerParams.sampler.magFilter == tcu::Sampler::NEAREST;
932         const bool isNearestOnly      = isNearestMinFilter && isNearestMagFilter;
933         const bool isSRGB = texFormat.order == tcu::TextureFormat::sRGB || texFormat.order == tcu::TextureFormat::sRGBA;
934         const int colorErrorBits = (isNearestOnly && !isSRGB) ? (1) : (2);
935         const tcu::IVec4 colorBits =
936             tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
937         tcu::LookupPrecision lookupPrecision;
938 
939         lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale;
940         lookupPrecision.coordBits      = tcu::IVec3(20, 20, 0);
941         lookupPrecision.uvwBits        = tcu::IVec3(5, 5, 0);
942         lookupPrecision.colorMask      = glu::TextureTestUtil::getCompareMask(pixelFormat);
943 
944         if (m_samplingFunction == SAMPLE_FILTER)
945         {
946             verificationOk = verifyTextureSampleResult(renderedFrame.getAccess(), &texCoord[0], samplerParams,
947                                                        lodPrecision, lookupPrecision);
948         }
949         else if (m_samplingFunction == SAMPLE_GATHER)
950         {
951             verificationOk =
952                 verifyTextureGatherResult(renderedFrame.getAccess(), &texCoord[0], samplerParams, lookupPrecision);
953         }
954         else
955         {
956             DE_ASSERT(false);
957             verificationOk = false;
958         }
959     }
960     else
961     {
962         tcu::TexComparePrecision texComparePrecision;
963         tcu::TexComparePrecision lowQualityTexComparePrecision;
964         tcu::LodPrecision lowQualityLodPrecision = lodPrecision;
965 
966         texComparePrecision.coordBits     = tcu::IVec3(20, 20, 0);
967         texComparePrecision.uvwBits       = tcu::IVec3(7, 7, 0);
968         texComparePrecision.pcfBits       = 5;
969         texComparePrecision.referenceBits = 16;
970         texComparePrecision.resultBits    = de::max(0, pixelFormat.redBits - 1);
971 
972         lowQualityTexComparePrecision.coordBits     = tcu::IVec3(20, 20, 0);
973         lowQualityTexComparePrecision.uvwBits       = tcu::IVec3(4, 4, 0);
974         lowQualityTexComparePrecision.pcfBits       = 0;
975         lowQualityTexComparePrecision.referenceBits = 16;
976         lowQualityTexComparePrecision.resultBits    = de::max(0, pixelFormat.redBits - 1);
977 
978         lowQualityLodPrecision.lodBits = 4;
979 
980         if (m_samplingFunction == SAMPLE_FILTER)
981         {
982             verificationOk =
983                 verifyTextureCompareResult(renderedFrame.getAccess(), &texCoord[0], samplerParams, texComparePrecision,
984                                            lowQualityTexComparePrecision, lodPrecision, lowQualityLodPrecision);
985         }
986         else if (m_samplingFunction == SAMPLE_GATHER)
987         {
988             verificationOk = verifyTextureGatherCmpResult(renderedFrame.getAccess(), &texCoord[0], samplerParams,
989                                                           texComparePrecision, lowQualityTexComparePrecision);
990         }
991         else
992         {
993             DE_ASSERT(false);
994             verificationOk = false;
995         }
996     }
997 
998     if (!verificationOk)
999         m_result.fail("Image verification failed");
1000 }
1001 
verifyTextureSampleResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoord,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::LodPrecision & lodPrecision,const tcu::LookupPrecision & lookupPrecision)1002 bool TextureBorderClampTest::verifyTextureSampleResult(const tcu::ConstPixelBufferAccess &renderedFrame,
1003                                                        const float *texCoord,
1004                                                        const glu::TextureTestUtil::ReferenceParams &samplerParams,
1005                                                        const tcu::LodPrecision &lodPrecision,
1006                                                        const tcu::LookupPrecision &lookupPrecision)
1007 {
1008     const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
1009     tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight());
1010     tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight());
1011     int numFailedPixels;
1012 
1013     glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(),
1014                                         texCoord, samplerParams);
1015 
1016     numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(
1017         renderedFrame, reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(), texCoord,
1018         samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog());
1019 
1020     if (numFailedPixels > 0)
1021         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels
1022                            << " invalid pixels!" << tcu::TestLog::EndMessage;
1023     m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1024                        << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1025     if (numFailedPixels > 0)
1026     {
1027         m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1028                            << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1029     }
1030     m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1031 
1032     return (numFailedPixels == 0);
1033 }
1034 
verifyTextureCompareResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoord,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::TexComparePrecision & texComparePrecision,const tcu::TexComparePrecision & lowQualityTexComparePrecision,const tcu::LodPrecision & lodPrecision,const tcu::LodPrecision & lowQualityLodPrecision)1035 bool TextureBorderClampTest::verifyTextureCompareResult(const tcu::ConstPixelBufferAccess &renderedFrame,
1036                                                         const float *texCoord,
1037                                                         const glu::TextureTestUtil::ReferenceParams &samplerParams,
1038                                                         const tcu::TexComparePrecision &texComparePrecision,
1039                                                         const tcu::TexComparePrecision &lowQualityTexComparePrecision,
1040                                                         const tcu::LodPrecision &lodPrecision,
1041                                                         const tcu::LodPrecision &lowQualityLodPrecision)
1042 {
1043     const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
1044     const int colorErrorBits           = 1;
1045     const tcu::IVec4 nonShadowBits =
1046         tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
1047     const tcu::Vec3 nonShadowThreshold = tcu::computeFixedPointThreshold(nonShadowBits).swizzle(1, 2, 3);
1048     std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage;
1049     const tcu::Texture2DView effectiveView =
1050         tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
1051     tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight());
1052     tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight());
1053     int numFailedPixels;
1054 
1055     glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), effectiveView, texCoord,
1056                                         samplerParams);
1057 
1058     numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(
1059         renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView, texCoord, samplerParams,
1060         texComparePrecision, lodPrecision, nonShadowThreshold);
1061 
1062     if (numFailedPixels > 0)
1063     {
1064         m_testCtx.getLog() << tcu::TestLog::Message
1065                            << "Warning: Verification assuming high-quality PCF filtering failed."
1066                            << tcu::TestLog::EndMessage;
1067 
1068         numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(
1069             renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView, texCoord, samplerParams,
1070             lowQualityTexComparePrecision, lowQualityLodPrecision, nonShadowThreshold);
1071 
1072         if (numFailedPixels > 0)
1073             m_testCtx.getLog() << tcu::TestLog::Message
1074                                << "ERROR: Verification against low precision requirements failed, failing test case."
1075                                << tcu::TestLog::EndMessage;
1076         else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1077             m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result");
1078     }
1079 
1080     if (numFailedPixels > 0)
1081         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels
1082                            << " invalid pixels!" << tcu::TestLog::EndMessage;
1083     m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1084                        << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1085     if (numFailedPixels > 0)
1086     {
1087         m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1088                            << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1089     }
1090     m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1091 
1092     return (numFailedPixels == 0);
1093 }
1094 
1095 template <typename T>
triQuadInterpolate(const T (& values)[4],float xFactor,float yFactor)1096 static inline T triQuadInterpolate(const T (&values)[4], float xFactor, float yFactor)
1097 {
1098     if (xFactor + yFactor < 1.0f)
1099         return values[0] + (values[2] - values[0]) * xFactor + (values[1] - values[0]) * yFactor;
1100     else
1101         return values[3] + (values[1] - values[3]) * (1.0f - xFactor) + (values[2] - values[3]) * (1.0f - yFactor);
1102 }
1103 
verifyTextureGatherResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoordArray,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::LookupPrecision & lookupPrecision)1104 bool TextureBorderClampTest::verifyTextureGatherResult(const tcu::ConstPixelBufferAccess &renderedFrame,
1105                                                        const float *texCoordArray,
1106                                                        const glu::TextureTestUtil::ReferenceParams &samplerParams,
1107                                                        const tcu::LookupPrecision &lookupPrecision)
1108 {
1109     const tcu::Vec2 texCoords[4] = {
1110         tcu::Vec2(texCoordArray[0], texCoordArray[1]),
1111         tcu::Vec2(texCoordArray[2], texCoordArray[3]),
1112         tcu::Vec2(texCoordArray[4], texCoordArray[5]),
1113         tcu::Vec2(texCoordArray[6], texCoordArray[7]),
1114     };
1115 
1116     const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
1117     const uint8_t fbColormask          = tcu::getColorMask(pixelFormat);
1118 
1119     std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage;
1120     const tcu::Texture2DView effectiveView =
1121         tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
1122 
1123     tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight());
1124     tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight());
1125     int numFailedPixels = 0;
1126 
1127     tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
1128 
1129     for (int py = 0; py < reference.getHeight(); ++py)
1130         for (int px = 0; px < reference.getWidth(); ++px)
1131         {
1132             const tcu::Vec2 viewportCoord = (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) /
1133                                             tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight());
1134             const tcu::Vec2 texCoord       = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
1135             const tcu::Vec4 referenceValue = effectiveView.gatherOffsets(
1136                 samplerParams.sampler, texCoord.x(), texCoord.y(), 0, glu::getDefaultGatherOffsets());
1137             const tcu::Vec4 referencePixel = referenceValue * samplerParams.colorScale + samplerParams.colorBias;
1138             const tcu::Vec4 resultPixel    = renderedFrame.getPixel(px, py);
1139             const tcu::Vec4 resultValue    = (resultPixel - samplerParams.colorBias) / samplerParams.colorScale;
1140 
1141             reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask));
1142 
1143             if (tcu::boolAny(tcu::logicalAnd(
1144                     lookupPrecision.colorMask,
1145                     tcu::greaterThan(tcu::absDiff(resultPixel, referencePixel), lookupPrecision.colorThreshold))))
1146             {
1147                 if (!tcu::isGatherOffsetsResultValid(effectiveView, samplerParams.sampler, lookupPrecision, texCoord, 0,
1148                                                      glu::getDefaultGatherOffsets(), resultValue))
1149                 {
1150                     errorMask.setPixel(px, py, tcu::RGBA::red());
1151                     ++numFailedPixels;
1152                 }
1153             }
1154         }
1155 
1156     if (numFailedPixels > 0)
1157         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels
1158                            << " invalid pixels!" << tcu::TestLog::EndMessage;
1159     m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1160                        << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1161     if (numFailedPixels > 0)
1162     {
1163         m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1164                            << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1165     }
1166     m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1167 
1168     return (numFailedPixels == 0);
1169 }
1170 
verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess & renderedFrame,const float * texCoordArray,const glu::TextureTestUtil::ReferenceParams & samplerParams,const tcu::TexComparePrecision & texComparePrecision,const tcu::TexComparePrecision & lowQualityTexComparePrecision)1171 bool TextureBorderClampTest::verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess &renderedFrame,
1172                                                           const float *texCoordArray,
1173                                                           const glu::TextureTestUtil::ReferenceParams &samplerParams,
1174                                                           const tcu::TexComparePrecision &texComparePrecision,
1175                                                           const tcu::TexComparePrecision &lowQualityTexComparePrecision)
1176 {
1177     const tcu::Vec2 texCoords[4] = {
1178         tcu::Vec2(texCoordArray[0], texCoordArray[1]),
1179         tcu::Vec2(texCoordArray[2], texCoordArray[3]),
1180         tcu::Vec2(texCoordArray[4], texCoordArray[5]),
1181         tcu::Vec2(texCoordArray[6], texCoordArray[7]),
1182     };
1183 
1184     std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage;
1185     const tcu::Texture2DView effectiveView =
1186         tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler);
1187 
1188     const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
1189     const tcu::BVec4 colorMask         = glu::TextureTestUtil::getCompareMask(pixelFormat);
1190     const uint8_t fbColormask          = tcu::getColorMask(pixelFormat);
1191     tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight());
1192     tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight());
1193     int numFailedPixels = 0;
1194     bool lowQuality     = false;
1195 
1196     tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
1197 
1198     for (int py = 0; py < reference.getHeight(); ++py)
1199         for (int px = 0; px < reference.getWidth(); ++px)
1200         {
1201             const tcu::Vec2 viewportCoord = (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) /
1202                                             tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight());
1203             const tcu::Vec2 texCoord       = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
1204             const float refZ               = samplerParams.ref;
1205             const tcu::Vec4 referenceValue = effectiveView.gatherOffsetsCompare(
1206                 samplerParams.sampler, refZ, texCoord.x(), texCoord.y(), glu::getDefaultGatherOffsets());
1207             const tcu::Vec4 resultValue = renderedFrame.getPixel(px, py);
1208 
1209             reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask));
1210 
1211             if (tcu::boolAny(tcu::logicalAnd(colorMask, tcu::notEqual(referenceValue, resultValue))))
1212             {
1213                 if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, texComparePrecision,
1214                                                             texCoord, glu::getDefaultGatherOffsets(), refZ,
1215                                                             resultValue))
1216                 {
1217                     lowQuality = true;
1218 
1219                     // fall back to low quality verification
1220                     if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler,
1221                                                                 lowQualityTexComparePrecision, texCoord,
1222                                                                 glu::getDefaultGatherOffsets(), refZ, resultValue))
1223                     {
1224                         errorMask.setPixel(px, py, tcu::RGBA::red());
1225                         ++numFailedPixels;
1226                     }
1227                 }
1228             }
1229         }
1230 
1231     if (numFailedPixels > 0)
1232         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels
1233                            << " invalid pixels!" << tcu::TestLog::EndMessage;
1234     else if (lowQuality)
1235     {
1236         m_testCtx.getLog() << tcu::TestLog::Message
1237                            << "Warning: Verification assuming high-quality PCF filtering failed."
1238                            << tcu::TestLog::EndMessage;
1239         m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result");
1240     }
1241 
1242     m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
1243                        << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
1244     if (numFailedPixels > 0)
1245     {
1246         m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
1247                            << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
1248     }
1249     m_testCtx.getLog() << tcu::TestLog::EndImageSet;
1250 
1251     return (numFailedPixels == 0);
1252 }
1253 
getTexture(void) const1254 const glu::Texture2D *TextureBorderClampTest::getTexture(void) const
1255 {
1256     return m_texture.get();
1257 }
1258 
getIterationSeed(const IterationConfig & config) const1259 uint32_t TextureBorderClampTest::getIterationSeed(const IterationConfig &config) const
1260 {
1261     tcu::SeedBuilder builder;
1262     builder << std::string(getName()) << m_iterationNdx << m_texFormat << config.minFilter << config.magFilter
1263             << m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight();
1264     return builder.get();
1265 }
1266 
genSamplerParams(const IterationConfig & config) const1267 glu::TextureTestUtil::ReferenceParams TextureBorderClampTest::genSamplerParams(const IterationConfig &config) const
1268 {
1269     const tcu::TextureFormat texFormat =
1270         tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode);
1271     glu::TextureTestUtil::ReferenceParams refParams(glu::TextureTestUtil::TEXTURETYPE_2D);
1272 
1273     refParams.sampler = glu::mapGLSampler(config.sWrapMode, config.tWrapMode, config.minFilter, config.magFilter);
1274     refParams.sampler.borderColor = config.borderColor;
1275     refParams.sampler.compare =
1276         (!m_useShadowSampler) ? (tcu::Sampler::COMPAREMODE_NONE) : (glu::mapGLCompareFunc(config.compareMode));
1277     refParams.sampler.depthStencilMode = m_sampleMode;
1278     refParams.lodMode                  = glu::TextureTestUtil::LODMODE_EXACT;
1279     refParams.samplerType              = (!m_useShadowSampler) ? (glu::TextureTestUtil::getSamplerType(texFormat)) :
1280                                                                  (glu::TextureTestUtil::SAMPLERTYPE_SHADOW);
1281     refParams.colorScale               = config.lookupScale;
1282     refParams.colorBias                = config.lookupBias;
1283     refParams.ref                      = config.compareRef;
1284 
1285     // compare can only be used with depth textures
1286     if (!isDepthFormat(m_texFormat, m_sampleMode))
1287         DE_ASSERT(refParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE);
1288 
1289     // sampler type must match compare mode
1290     DE_ASSERT(m_useShadowSampler == (config.compareMode != GL_NONE));
1291 
1292     // in gather, weird mapping is most likely an error
1293     if (m_samplingFunction == SAMPLE_GATHER)
1294     {
1295         DE_ASSERT(refParams.colorScale == tcu::Vec4(refParams.colorScale.x()));
1296         DE_ASSERT(refParams.colorBias == tcu::Vec4(refParams.colorBias.x()));
1297     }
1298 
1299     return refParams;
1300 }
1301 
genGatherProgram(void) const1302 glu::ShaderProgram *TextureBorderClampTest::genGatherProgram(void) const
1303 {
1304     const std::string glslVersionDecl =
1305         glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()));
1306     const std::string vtxSource = glslVersionDecl + "\n"
1307                                                     "in highp vec4 a_position;\n"
1308                                                     "in highp vec2 a_texcoord;\n"
1309                                                     "out highp vec2 v_texcoord;\n"
1310                                                     "void main()\n"
1311                                                     "{\n"
1312                                                     "    gl_Position = a_position;\n"
1313                                                     "    v_texcoord = a_texcoord;\n"
1314                                                     "}\n";
1315     const char *samplerType;
1316     const char *lookup;
1317     std::ostringstream fragSource;
1318 
1319     if (m_useShadowSampler)
1320     {
1321         samplerType = "sampler2DShadow";
1322         lookup      = "textureGather(u_sampler, v_texcoord, u_ref)";
1323     }
1324     else
1325     {
1326         switch (m_channelClass)
1327         {
1328         case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1329         case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1330         case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1331             samplerType = "sampler2D";
1332             lookup      = "textureGather(u_sampler, v_texcoord)";
1333             break;
1334 
1335         case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1336             samplerType = "isampler2D";
1337             lookup      = "vec4(textureGather(u_sampler, v_texcoord))";
1338             break;
1339 
1340         case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1341             samplerType = "usampler2D";
1342             lookup      = "vec4(textureGather(u_sampler, v_texcoord))";
1343             break;
1344 
1345         default:
1346             samplerType = "";
1347             lookup      = "";
1348             DE_ASSERT(false);
1349         }
1350     }
1351 
1352     fragSource << glslVersionDecl + "\n"
1353                                     "uniform highp "
1354                << samplerType
1355                << " u_sampler;\n"
1356                   "uniform highp vec4 u_colorScale;\n"
1357                   "uniform highp vec4 u_colorBias;\n"
1358                << ((m_useShadowSampler) ? ("uniform highp float u_ref;\n") : (""))
1359                << "in highp vec2 v_texcoord;\n"
1360                   "layout(location=0) out highp vec4 o_color;\n"
1361                   "void main()\n"
1362                   "{\n"
1363                   "    o_color = "
1364                << lookup
1365                << " * u_colorScale + u_colorBias;\n"
1366                   "}\n";
1367 
1368     return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
1369                                                                     << glu::VertexSource(vtxSource)
1370                                                                     << glu::FragmentSource(fragSource.str()));
1371 }
1372 
1373 class TextureBorderClampFormatCase : public TextureBorderClampTest
1374 {
1375 public:
1376     TextureBorderClampFormatCase(Context &context, const char *name, const char *description, uint32_t texFormat,
1377                                  tcu::Sampler::DepthStencilMode mode, StateType stateType, SizeType sizeType,
1378                                  uint32_t filter, SamplingFunction samplingFunction);
1379 
1380 private:
1381     void init(void);
1382 
1383     int getNumIterations(void) const;
1384     IterationConfig getIteration(int ndx) const;
1385 
1386     const SizeType m_sizeType;
1387 
1388     std::vector<IterationConfig> m_iterations;
1389 };
1390 
TextureBorderClampFormatCase(Context & context,const char * name,const char * description,uint32_t texFormat,tcu::Sampler::DepthStencilMode mode,StateType stateType,SizeType sizeType,uint32_t filter,SamplingFunction samplingFunction)1391 TextureBorderClampFormatCase::TextureBorderClampFormatCase(Context &context, const char *name, const char *description,
1392                                                            uint32_t texFormat, tcu::Sampler::DepthStencilMode mode,
1393                                                            StateType stateType, SizeType sizeType, uint32_t filter,
1394                                                            SamplingFunction samplingFunction)
1395     : TextureBorderClampTest(context, name, description, texFormat, mode, stateType,
1396                              (sizeType == SIZE_POT) ? (32) : (17), (sizeType == SIZE_POT) ? (16) : (31),
1397                              samplingFunction, filter, FLAG_TEST_FLOAT_FILTERABLE)
1398     , m_sizeType(sizeType)
1399 {
1400     if (m_sizeType == SIZE_POT)
1401         DE_ASSERT(deIsPowerOfTwo32(m_texWidth) && deIsPowerOfTwo32(m_texHeight));
1402     else
1403         DE_ASSERT(!deIsPowerOfTwo32(m_texWidth) && !deIsPowerOfTwo32(m_texHeight));
1404 
1405     if (glu::isCompressedFormat(texFormat))
1406     {
1407         const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(texFormat);
1408         const tcu::IVec3 blockPixelSize                 = tcu::getBlockPixelSize(compressedFormat);
1409 
1410         // is (not) multiple of a block size
1411         if (m_sizeType == SIZE_POT)
1412             DE_ASSERT((m_texWidth % blockPixelSize.x()) == 0 && (m_texHeight % blockPixelSize.y()) == 0);
1413         else
1414             DE_ASSERT((m_texWidth % blockPixelSize.x()) != 0 && (m_texHeight % blockPixelSize.y()) != 0);
1415 
1416         DE_UNREF(blockPixelSize);
1417     }
1418 }
1419 
init(void)1420 void TextureBorderClampFormatCase::init(void)
1421 {
1422     TextureBorderClampTest::init();
1423 
1424     // \note TextureBorderClampTest::init() creates texture
1425     const tcu::TextureFormat texFormat =
1426         tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1427     const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat);
1428 
1429     // iterations
1430 
1431     {
1432         IterationConfig iteration;
1433         iteration.p0          = tcu::Vec2(-1.5f, -3.0f);
1434         iteration.p1          = tcu::Vec2(1.5f, 2.5f);
1435         iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.3f, 0.7f, 0.2f, 0.5f));
1436         m_iterations.push_back(iteration);
1437     }
1438     {
1439         IterationConfig iteration;
1440         iteration.p0          = tcu::Vec2(-0.5f, 0.75f);
1441         iteration.p1          = tcu::Vec2(0.25f, 1.25f);
1442         iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.9f, 0.2f, 0.4f, 0.6f));
1443         m_iterations.push_back(iteration);
1444     }
1445 
1446     // common parameters
1447     for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
1448     {
1449         IterationConfig &iteration = m_iterations[ndx];
1450 
1451         if (m_samplingFunction == SAMPLE_GATHER)
1452         {
1453             iteration.lookupScale = tcu::Vec4(texFormatInfo.lookupScale.x());
1454             iteration.lookupBias  = tcu::Vec4(texFormatInfo.lookupBias.x());
1455         }
1456         else
1457         {
1458             iteration.lookupScale = texFormatInfo.lookupScale;
1459             iteration.lookupBias  = texFormatInfo.lookupBias;
1460         }
1461 
1462         iteration.minFilter   = m_filter;
1463         iteration.magFilter   = m_filter;
1464         iteration.sWrapMode   = GL_CLAMP_TO_BORDER;
1465         iteration.tWrapMode   = GL_CLAMP_TO_BORDER;
1466         iteration.compareMode = GL_NONE;
1467         iteration.compareRef  = 0.0f;
1468     }
1469 }
1470 
getNumIterations(void) const1471 int TextureBorderClampFormatCase::getNumIterations(void) const
1472 {
1473     return (int)m_iterations.size();
1474 }
1475 
getIteration(int ndx) const1476 TextureBorderClampTest::IterationConfig TextureBorderClampFormatCase::getIteration(int ndx) const
1477 {
1478     return m_iterations[ndx];
1479 }
1480 
1481 class TextureBorderClampRangeClampCase : public TextureBorderClampTest
1482 {
1483 public:
1484     TextureBorderClampRangeClampCase(Context &context, const char *name, const char *description, uint32_t texFormat,
1485                                      tcu::Sampler::DepthStencilMode mode, uint32_t filter);
1486 
1487 private:
1488     void init(void);
1489 
1490     int getNumIterations(void) const;
1491     IterationConfig getIteration(int ndx) const;
1492 
1493     std::vector<IterationConfig> m_iterations;
1494 };
1495 
TextureBorderClampRangeClampCase(Context & context,const char * name,const char * description,uint32_t texFormat,tcu::Sampler::DepthStencilMode mode,uint32_t filter)1496 TextureBorderClampRangeClampCase::TextureBorderClampRangeClampCase(Context &context, const char *name,
1497                                                                    const char *description, uint32_t texFormat,
1498                                                                    tcu::Sampler::DepthStencilMode mode, uint32_t filter)
1499     : TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM,
1500                              8, 32, SAMPLE_FILTER, filter, FLAG_TEST_FLOAT_FILTERABLE)
1501 {
1502 }
1503 
init(void)1504 void TextureBorderClampRangeClampCase::init(void)
1505 {
1506     TextureBorderClampTest::init();
1507 
1508     const tcu::TextureFormat texFormat =
1509         tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1510     const bool isDepth = isDepthFormat(m_texFormat, m_sampleMode);
1511     const bool isFloat = m_channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
1512     const bool isFixed = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1513                          m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
1514     const bool isPureInteger = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ||
1515                                m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
1516 
1517     if (isDepth || isFloat)
1518     {
1519         // infinities are commonly used values on depth/float borders
1520         {
1521             IterationConfig iteration;
1522             iteration.p0          = tcu::Vec2(-1.2f, -3.0f);
1523             iteration.p1          = tcu::Vec2(1.2f, 2.5f);
1524             iteration.borderColor = rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity()));
1525             iteration.lookupScale =
1526                 tcu::Vec4(0.5f); // scale & bias to [0.25, 0.5] range to make out-of-range values visible
1527             iteration.lookupBias  = tcu::Vec4(0.25f);
1528             iteration.description = "border value infinity";
1529             m_iterations.push_back(iteration);
1530         }
1531         {
1532             IterationConfig iteration;
1533             iteration.p0          = tcu::Vec2(-0.25f, -0.75f);
1534             iteration.p1          = tcu::Vec2(2.25f, 1.25f);
1535             iteration.borderColor = rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity()));
1536             iteration.lookupScale = tcu::Vec4(0.5f);
1537             iteration.lookupBias  = tcu::Vec4(0.25f);
1538             iteration.description = "border value negative infinity";
1539             m_iterations.push_back(iteration);
1540         }
1541     }
1542     else if (isPureInteger)
1543     {
1544         const tcu::IVec4 numBits = tcu::getTextureFormatBitDepth(texFormat);
1545         const bool isSigned      = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER;
1546 
1547         // can't overflow 32bit integers with 32bit integers
1548         for (int ndx = 0; ndx < 4; ++ndx)
1549             DE_ASSERT(numBits[ndx] == 0 || numBits[ndx] == 8 || numBits[ndx] == 16);
1550 
1551         const tcu::IVec4 minValue   = getNBitIntegerVec4MinValue(isSigned, numBits);
1552         const tcu::IVec4 maxValue   = getNBitIntegerVec4MaxValue(isSigned, numBits);
1553         const tcu::IVec4 valueRange = maxValue - minValue;
1554         const tcu::IVec4 divSafeRange(
1555             (valueRange[0] == 0) ? (1) : (valueRange[0]), (valueRange[1] == 0) ? (1) : (valueRange[1]),
1556             (valueRange[2] == 0) ? (1) : (valueRange[2]), (valueRange[3] == 0) ? (1) : (valueRange[3]));
1557 
1558         // format max
1559         {
1560             const tcu::IVec4 value = maxValue + tcu::IVec4(1);
1561 
1562             IterationConfig iteration;
1563             iteration.p0          = tcu::Vec2(-1.2f, -3.0f);
1564             iteration.p1          = tcu::Vec2(1.2f, 2.5f);
1565             iteration.borderColor = (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<uint32_t>()));
1566             iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1567             iteration.lookupBias  = (isSigned) ? (tcu::Vec4(0.5f)) : (tcu::Vec4(0.25f));
1568             iteration.description = "border values one larger than maximum";
1569             m_iterations.push_back(iteration);
1570         }
1571         // format min
1572         if (isSigned)
1573         {
1574             const tcu::IVec4 value = minValue - tcu::IVec4(1);
1575 
1576             IterationConfig iteration;
1577             iteration.p0          = tcu::Vec2(-0.25f, -0.75f);
1578             iteration.p1          = tcu::Vec2(2.25f, 1.25f);
1579             iteration.borderColor = rr::GenericVec4(value);
1580             iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1581             iteration.lookupBias  = tcu::Vec4(0.5f);
1582             iteration.description = "border values one less than minimum";
1583             m_iterations.push_back(iteration);
1584         }
1585         // (u)int32 max
1586         {
1587             const tcu::IVec4 value = (isSigned) ? (tcu::IVec4(std::numeric_limits<int32_t>::max())) :
1588                                                   (tcu::IVec4(std::numeric_limits<uint32_t>::max()));
1589 
1590             IterationConfig iteration;
1591             iteration.p0          = tcu::Vec2(-1.6f, -2.1f);
1592             iteration.p1          = tcu::Vec2(1.2f, 3.5f);
1593             iteration.borderColor = (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<uint32_t>()));
1594             iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1595             iteration.lookupBias  = tcu::Vec4(0.25f);
1596             iteration.description = "border values 32-bit maximum";
1597             m_iterations.push_back(iteration);
1598         }
1599         // int32 min
1600         if (isSigned)
1601         {
1602             const tcu::IVec4 value = tcu::IVec4(std::numeric_limits<int32_t>::min());
1603 
1604             IterationConfig iteration;
1605             iteration.p0          = tcu::Vec2(-2.6f, -4.0f);
1606             iteration.p1          = tcu::Vec2(1.1f, 1.5f);
1607             iteration.borderColor = rr::GenericVec4(value);
1608             iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>();
1609             iteration.lookupBias  = tcu::Vec4(0.25f);
1610             iteration.description = "border values 0";
1611             m_iterations.push_back(iteration);
1612         }
1613     }
1614     else if (isFixed)
1615     {
1616         const bool isSigned = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;
1617         const tcu::Vec4 lookupBias =
1618             (isSigned) ? (tcu::Vec4(0.5f)) :
1619                          (tcu::Vec4(0.25f)); // scale & bias to [0.25, 0.5] range to make out-of-range values visible
1620         const tcu::Vec4 lookupScale = (isSigned) ? (tcu::Vec4(0.25f)) : (tcu::Vec4(0.5f));
1621 
1622         {
1623             IterationConfig iteration;
1624             iteration.p0          = tcu::Vec2(-1.2f, -3.0f);
1625             iteration.p1          = tcu::Vec2(1.2f, 2.5f);
1626             iteration.borderColor = mapToFormatColorUnits(texFormat, tcu::Vec4(1.1f, 1.3f, 2.2f, 1.3f));
1627             iteration.lookupScale = lookupScale;
1628             iteration.lookupBias  = lookupBias;
1629             iteration.description = "border values larger than maximum";
1630             m_iterations.push_back(iteration);
1631         }
1632         {
1633             IterationConfig iteration;
1634             iteration.p0          = tcu::Vec2(-0.25f, -0.75f);
1635             iteration.p1          = tcu::Vec2(2.25f, 1.25f);
1636             iteration.borderColor = mapToFormatColorUnits(texFormat, tcu::Vec4(-0.2f, -0.9f, -2.4f, -0.6f));
1637             iteration.lookupScale = lookupScale;
1638             iteration.lookupBias  = lookupBias;
1639             iteration.description = "border values less than minimum";
1640             m_iterations.push_back(iteration);
1641         }
1642     }
1643     else
1644         DE_ASSERT(false);
1645 
1646     // common parameters
1647     for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
1648     {
1649         IterationConfig &iteration = m_iterations[ndx];
1650 
1651         iteration.minFilter   = m_filter;
1652         iteration.magFilter   = m_filter;
1653         iteration.sWrapMode   = GL_CLAMP_TO_BORDER;
1654         iteration.tWrapMode   = GL_CLAMP_TO_BORDER;
1655         iteration.compareMode = GL_NONE;
1656         iteration.compareRef  = 0.0f;
1657     }
1658 }
1659 
getNumIterations(void) const1660 int TextureBorderClampRangeClampCase::getNumIterations(void) const
1661 {
1662     return (int)m_iterations.size();
1663 }
1664 
getIteration(int ndx) const1665 TextureBorderClampTest::IterationConfig TextureBorderClampRangeClampCase::getIteration(int ndx) const
1666 {
1667     return m_iterations[ndx];
1668 }
1669 
1670 class TextureBorderClampPerAxisCase2D : public TextureBorderClampTest
1671 {
1672 public:
1673     TextureBorderClampPerAxisCase2D(Context &context, const char *name, const char *description, uint32_t texFormat,
1674                                     tcu::Sampler::DepthStencilMode mode, SizeType sizeType, uint32_t filter,
1675                                     uint32_t texSWrap, uint32_t texTWrap, SamplingFunction samplingFunction);
1676 
1677 private:
1678     void init(void);
1679 
1680     int getNumIterations(void) const;
1681     IterationConfig getIteration(int ndx) const;
1682 
1683     const uint32_t m_texSWrap;
1684     const uint32_t m_texTWrap;
1685 
1686     std::vector<IterationConfig> m_iterations;
1687 };
1688 
TextureBorderClampPerAxisCase2D(Context & context,const char * name,const char * description,uint32_t texFormat,tcu::Sampler::DepthStencilMode mode,SizeType sizeType,uint32_t filter,uint32_t texSWrap,uint32_t texTWrap,SamplingFunction samplingFunction)1689 TextureBorderClampPerAxisCase2D::TextureBorderClampPerAxisCase2D(Context &context, const char *name,
1690                                                                  const char *description, uint32_t texFormat,
1691                                                                  tcu::Sampler::DepthStencilMode mode, SizeType sizeType,
1692                                                                  uint32_t filter, uint32_t texSWrap, uint32_t texTWrap,
1693                                                                  SamplingFunction samplingFunction)
1694     : TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM,
1695                              (sizeType == SIZE_POT) ? (16) : (7), (sizeType == SIZE_POT) ? (8) : (9), samplingFunction,
1696                              filter, FLAG_TEST_FLOAT_FILTERABLE)
1697     , m_texSWrap(texSWrap)
1698     , m_texTWrap(texTWrap)
1699 {
1700 }
1701 
init(void)1702 void TextureBorderClampPerAxisCase2D::init(void)
1703 {
1704     TextureBorderClampTest::init();
1705 
1706     // \note TextureBorderClampTest::init() creates texture
1707     const tcu::TextureFormat texFormat =
1708         tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1709     const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat);
1710 
1711     IterationConfig iteration;
1712     iteration.p0          = tcu::Vec2(-0.25f, -0.75f);
1713     iteration.p1          = tcu::Vec2(2.25f, 1.25f);
1714     iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.4f, 0.9f, 0.1f, 0.2f));
1715 
1716     if (m_samplingFunction == SAMPLE_GATHER)
1717     {
1718         iteration.lookupScale = tcu::Vec4(texFormatInfo.lookupScale.x());
1719         iteration.lookupBias  = tcu::Vec4(texFormatInfo.lookupBias.x());
1720     }
1721     else
1722     {
1723         iteration.lookupScale = texFormatInfo.lookupScale;
1724         iteration.lookupBias  = texFormatInfo.lookupBias;
1725     }
1726 
1727     iteration.minFilter   = m_filter;
1728     iteration.magFilter   = m_filter;
1729     iteration.sWrapMode   = m_texSWrap;
1730     iteration.tWrapMode   = m_texTWrap;
1731     iteration.compareMode = GL_NONE;
1732     iteration.compareRef  = 0.0f;
1733 
1734     m_iterations.push_back(iteration);
1735 }
1736 
getNumIterations(void) const1737 int TextureBorderClampPerAxisCase2D::getNumIterations(void) const
1738 {
1739     return (int)m_iterations.size();
1740 }
1741 
getIteration(int ndx) const1742 TextureBorderClampTest::IterationConfig TextureBorderClampPerAxisCase2D::getIteration(int ndx) const
1743 {
1744     return m_iterations[ndx];
1745 }
1746 
1747 class TextureBorderClampDepthCompareCase : public TextureBorderClampTest
1748 {
1749 public:
1750     TextureBorderClampDepthCompareCase(Context &context, const char *name, const char *description, uint32_t texFormat,
1751                                        SizeType sizeType, uint32_t filter, SamplingFunction samplingFunction);
1752 
1753 private:
1754     void init(void);
1755 
1756     int getNumIterations(void) const;
1757     IterationConfig getIteration(int ndx) const;
1758 
1759     std::vector<IterationConfig> m_iterations;
1760 };
1761 
TextureBorderClampDepthCompareCase(Context & context,const char * name,const char * description,uint32_t texFormat,SizeType sizeType,uint32_t filter,SamplingFunction samplingFunction)1762 TextureBorderClampDepthCompareCase::TextureBorderClampDepthCompareCase(Context &context, const char *name,
1763                                                                        const char *description, uint32_t texFormat,
1764                                                                        SizeType sizeType, uint32_t filter,
1765                                                                        SamplingFunction samplingFunction)
1766     : TextureBorderClampTest(context, name, description, texFormat, tcu::Sampler::MODE_DEPTH,
1767                              TextureBorderClampTest::STATE_TEXTURE_PARAM, (sizeType == SIZE_POT) ? (32) : (13),
1768                              (sizeType == SIZE_POT) ? (16) : (17), samplingFunction, filter, FLAG_USE_SHADOW_SAMPLER)
1769 {
1770 }
1771 
init(void)1772 void TextureBorderClampDepthCompareCase::init(void)
1773 {
1774     TextureBorderClampTest::init();
1775 
1776     // 0.5 <= 0.7
1777     {
1778         IterationConfig iteration;
1779         iteration.p0          = tcu::Vec2(-0.15f, -0.35f);
1780         iteration.p1          = tcu::Vec2(1.25f, 1.1f);
1781         iteration.borderColor = rr::GenericVec4(tcu::Vec4(0.7f, 0.0f, 0.0f, 0.0f));
1782         iteration.description = "Border color in [0, 1] range";
1783         iteration.compareMode = GL_LEQUAL;
1784         iteration.compareRef  = 0.5f;
1785         m_iterations.push_back(iteration);
1786     }
1787 
1788     // 1.5 <= 1.0
1789     {
1790         IterationConfig iteration;
1791         iteration.p0          = tcu::Vec2(-0.15f, -0.35f);
1792         iteration.p1          = tcu::Vec2(1.25f, 1.1f);
1793         iteration.borderColor = rr::GenericVec4(tcu::Vec4(1.5f, 0.0f, 0.0f, 0.0f));
1794         iteration.description = "Border color > 1, should be clamped";
1795         iteration.compareMode = GL_LEQUAL;
1796         iteration.compareRef  = 1.0f;
1797         m_iterations.push_back(iteration);
1798     }
1799 
1800     // -0.5 >= 0.0
1801     {
1802         IterationConfig iteration;
1803         iteration.p0          = tcu::Vec2(-0.15f, -0.35f);
1804         iteration.p1          = tcu::Vec2(1.25f, 1.1f);
1805         iteration.borderColor = rr::GenericVec4(tcu::Vec4(-0.5f, 0.0f, 0.0f, 0.0f));
1806         iteration.description = "Border color < 0, should be clamped";
1807         iteration.compareMode = GL_GEQUAL;
1808         iteration.compareRef  = 0.0f;
1809         m_iterations.push_back(iteration);
1810     }
1811 
1812     // inf < 1.25
1813     {
1814         IterationConfig iteration;
1815         iteration.p0          = tcu::Vec2(-0.15f, -0.35f);
1816         iteration.p1          = tcu::Vec2(1.25f, 1.1f);
1817         iteration.borderColor = rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f));
1818         iteration.description = "Border color == inf, should be clamped; ref > 1";
1819         iteration.compareMode = GL_LESS;
1820         iteration.compareRef  = 1.25f;
1821         m_iterations.push_back(iteration);
1822     }
1823 
1824     // -inf > -0.5
1825     {
1826         IterationConfig iteration;
1827         iteration.p0          = tcu::Vec2(-0.15f, -0.35f);
1828         iteration.p1          = tcu::Vec2(1.25f, 1.1f);
1829         iteration.borderColor = rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f));
1830         iteration.description = "Border color == inf, should be clamped; ref < 0";
1831         iteration.compareMode = GL_GREATER;
1832         iteration.compareRef  = -0.5f;
1833         m_iterations.push_back(iteration);
1834     }
1835 
1836     // common parameters
1837     for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx)
1838     {
1839         IterationConfig &iteration = m_iterations[ndx];
1840 
1841         iteration.lookupScale = tcu::Vec4(1.0);
1842         iteration.lookupBias  = tcu::Vec4(0.0);
1843         iteration.minFilter   = m_filter;
1844         iteration.magFilter   = m_filter;
1845         iteration.sWrapMode   = GL_CLAMP_TO_BORDER;
1846         iteration.tWrapMode   = GL_CLAMP_TO_BORDER;
1847     }
1848 }
1849 
getNumIterations(void) const1850 int TextureBorderClampDepthCompareCase::getNumIterations(void) const
1851 {
1852     return (int)m_iterations.size();
1853 }
1854 
getIteration(int ndx) const1855 TextureBorderClampTest::IterationConfig TextureBorderClampDepthCompareCase::getIteration(int ndx) const
1856 {
1857     return m_iterations[ndx];
1858 }
1859 
1860 class TextureBorderClampUnusedChannelCase : public TextureBorderClampTest
1861 {
1862 public:
1863     TextureBorderClampUnusedChannelCase(Context &context, const char *name, const char *description, uint32_t texFormat,
1864                                         tcu::Sampler::DepthStencilMode depthStencilMode);
1865 
1866 private:
1867     void init(void);
1868 
1869     int getNumIterations(void) const;
1870     IterationConfig getIteration(int ndx) const;
1871 
1872     std::vector<IterationConfig> m_iterations;
1873 };
1874 
TextureBorderClampUnusedChannelCase(Context & context,const char * name,const char * description,uint32_t texFormat,tcu::Sampler::DepthStencilMode depthStencilMode)1875 TextureBorderClampUnusedChannelCase::TextureBorderClampUnusedChannelCase(
1876     Context &context, const char *name, const char *description, uint32_t texFormat,
1877     tcu::Sampler::DepthStencilMode depthStencilMode)
1878     : TextureBorderClampTest(context, name, description, texFormat, depthStencilMode,
1879                              TextureBorderClampTest::STATE_TEXTURE_PARAM, 8, 8, SAMPLE_FILTER, GL_NEAREST)
1880 {
1881 }
1882 
selectComponents(const rr::GenericVec4 & trueComponents,const rr::GenericVec4 & falseComponents,const tcu::BVec4 & m)1883 static rr::GenericVec4 selectComponents(const rr::GenericVec4 &trueComponents, const rr::GenericVec4 &falseComponents,
1884                                         const tcu::BVec4 &m)
1885 {
1886     return rr::GenericVec4(tcu::select(trueComponents.get<uint32_t>(), falseComponents.get<uint32_t>(), m));
1887 }
1888 
init(void)1889 void TextureBorderClampUnusedChannelCase::init(void)
1890 {
1891     TextureBorderClampTest::init();
1892 
1893     // \note TextureBorderClampTest::init() creates texture
1894     const tcu::TextureFormat texFormat =
1895         tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode);
1896     const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat);
1897     const tcu::BVec4 channelMask               = tcu::getTextureFormatChannelMask(texFormat);
1898     const float maxChannelValue                = (channelMask[0]) ? (texFormatInfo.valueMax[0]) :
1899                                                  (channelMask[1]) ? (texFormatInfo.valueMax[1]) :
1900                                                  (channelMask[2]) ? (texFormatInfo.valueMax[2]) :
1901                                                                     (texFormatInfo.valueMax[3]);
1902 
1903     const rr::GenericVec4 effectiveColors = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.6f));
1904     rr::GenericVec4 nonEffectiveColors;
1905 
1906     switch (m_channelClass)
1907     {
1908     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1909     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1910     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1911         nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f));
1912         break;
1913 
1914     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1915         nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<int32_t>());
1916         break;
1917 
1918     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1919         nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<uint32_t>());
1920         break;
1921     default:
1922         DE_ASSERT(false);
1923     }
1924 
1925     IterationConfig iteration;
1926     iteration.p0          = tcu::Vec2(-0.25f, -0.75f);
1927     iteration.p1          = tcu::Vec2(2.25f, 1.25f);
1928     iteration.borderColor = selectComponents(effectiveColors, nonEffectiveColors, channelMask);
1929     iteration.lookupScale = texFormatInfo.lookupScale;
1930     iteration.lookupBias  = texFormatInfo.lookupBias;
1931     iteration.minFilter   = GL_NEAREST;
1932     iteration.magFilter   = GL_NEAREST;
1933     iteration.sWrapMode   = GL_CLAMP_TO_BORDER;
1934     iteration.tWrapMode   = GL_CLAMP_TO_BORDER;
1935     iteration.compareMode = GL_NONE;
1936     iteration.compareRef  = 0.0f;
1937     iteration.description = "Setting values to unused border color components";
1938 
1939     m_iterations.push_back(iteration);
1940 }
1941 
getNumIterations(void) const1942 int TextureBorderClampUnusedChannelCase::getNumIterations(void) const
1943 {
1944     return (int)m_iterations.size();
1945 }
1946 
getIteration(int ndx) const1947 TextureBorderClampTest::IterationConfig TextureBorderClampUnusedChannelCase::getIteration(int ndx) const
1948 {
1949     return m_iterations[ndx];
1950 }
1951 
1952 class TextureBorderClampPerAxisCase3D : public TestCase
1953 {
1954 public:
1955     TextureBorderClampPerAxisCase3D(Context &context, const char *name, const char *description, uint32_t texFormat,
1956                                     SizeType size, uint32_t filter, uint32_t sWrap, uint32_t tWrap, uint32_t rWrap);
1957 
1958 private:
1959     void init(void);
1960     void deinit(void);
1961     IterateResult iterate(void);
1962 
1963     void renderTo(tcu::Surface &surface, const glu::TextureTestUtil::ReferenceParams &samplerParams);
1964 
1965     void logParams(const glu::TextureTestUtil::ReferenceParams &samplerParams);
1966 
1967     void verifyImage(const tcu::Surface &image, const glu::TextureTestUtil::ReferenceParams &samplerParams);
1968 
1969     glu::TextureTestUtil::ReferenceParams getSamplerParams(void) const;
1970     uint32_t getCaseSeed(void) const;
1971 
1972     enum
1973     {
1974         VIEWPORT_WIDTH  = 128,
1975         VIEWPORT_HEIGHT = 128,
1976     };
1977 
1978     const uint32_t m_texFormat;
1979     const tcu::TextureChannelClass m_channelClass;
1980     const tcu::IVec3 m_size;
1981     const uint32_t m_filter;
1982     const uint32_t m_sWrap;
1983     const uint32_t m_tWrap;
1984     const uint32_t m_rWrap;
1985 
1986     de::MovePtr<glu::Texture3D> m_texture;
1987     de::MovePtr<gls::TextureTestUtil::TextureRenderer> m_renderer;
1988 
1989     rr::GenericVec4 m_borderColor;
1990     std::vector<float> m_texCoords;
1991     tcu::Vec4 m_lookupScale;
1992     tcu::Vec4 m_lookupBias;
1993 };
1994 
TextureBorderClampPerAxisCase3D(Context & context,const char * name,const char * description,uint32_t texFormat,SizeType size,uint32_t filter,uint32_t sWrap,uint32_t tWrap,uint32_t rWrap)1995 TextureBorderClampPerAxisCase3D::TextureBorderClampPerAxisCase3D(Context &context, const char *name,
1996                                                                  const char *description, uint32_t texFormat,
1997                                                                  SizeType size, uint32_t filter, uint32_t sWrap,
1998                                                                  uint32_t tWrap, uint32_t rWrap)
1999     : TestCase(context, name, description)
2000     , m_texFormat(texFormat)
2001     , m_channelClass(getFormatChannelClass(texFormat, tcu::Sampler::MODE_LAST))
2002     , m_size((size == SIZE_POT) ? (tcu::IVec3(8, 16, 4)) : (tcu::IVec3(13, 5, 7)))
2003     , m_filter(filter)
2004     , m_sWrap(sWrap)
2005     , m_tWrap(tWrap)
2006     , m_rWrap(rWrap)
2007 {
2008 }
2009 
init(void)2010 void TextureBorderClampPerAxisCase3D::init(void)
2011 {
2012     auto ctxType            = m_context.getRenderContext().getType();
2013     const bool isES32orGL45 = glu::contextSupports(ctxType, glu::ApiType::es(3, 2)) ||
2014                               glu::contextSupports(ctxType, glu::ApiType::core(4, 5));
2015     const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(ctxType);
2016 
2017     // repeat filterable test with valid context
2018     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2019     const bool is_texture_float_linear_supported =
2020         glu::hasExtension(gl, glu::ApiType::es(3, 0), "GL_OES_texture_float_linear");
2021     const bool coreFilterable =
2022         isCoreFilterableFormat(m_texFormat, tcu::Sampler::MODE_LAST, is_texture_float_linear_supported);
2023 
2024     if (!coreFilterable && filterRequiresFilterability(m_filter))
2025         throw tcu::NotSupportedError("Test requires GL_OES_texture_float_linear extension");
2026 
2027     if (!isES32orGL45 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp"))
2028         throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension");
2029 
2030     if (glu::isCompressedFormat(m_texFormat) && !isES32orGL45 &&
2031         tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat)) &&
2032         !m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr"))
2033     {
2034         throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension");
2035     }
2036     if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888"))
2037         throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension");
2038     if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH ||
2039         m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT)
2040     {
2041         throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" +
2042                                      de::toString<int>(VIEWPORT_HEIGHT) + " viewport");
2043     }
2044 
2045     // resources
2046     m_texture = genDefaultTexture<glu::Texture3D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat,
2047                                                   m_size);
2048     m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(
2049         m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP));
2050 
2051     // texture info
2052     m_testCtx.getLog() << tcu::TestLog::Message << "Created 3D texture with format "
2053                        << glu::getTextureFormatName(m_texFormat) << ", size (" << m_texture->getRefTexture().getWidth()
2054                        << ", " << m_texture->getRefTexture().getHeight() << ", "
2055                        << m_texture->getRefTexture().getDepth() << ")\n"
2056                        << tcu::TestLog::EndMessage;
2057 
2058     // tex coord
2059     {
2060         m_testCtx.getLog() << tcu::TestLog::Message
2061                            << "Setting tex coords bottom-left: (-1, -1, -1.5), top-right (2, 2, 2.5)\n"
2062                            << tcu::TestLog::EndMessage;
2063 
2064         m_texCoords.resize(4 * 3);
2065 
2066         m_texCoords[0]  = -1.0f;
2067         m_texCoords[1]  = -1.0f;
2068         m_texCoords[2]  = -1.5f;
2069         m_texCoords[3]  = -1.0f;
2070         m_texCoords[4]  = 2.0f;
2071         m_texCoords[5]  = 0.5f;
2072         m_texCoords[6]  = 2.0f;
2073         m_texCoords[7]  = -1.0f;
2074         m_texCoords[8]  = 0.5f;
2075         m_texCoords[9]  = 2.0f;
2076         m_texCoords[10] = 2.0f;
2077         m_texCoords[11] = 2.5f;
2078     }
2079 
2080     // set render params
2081     {
2082         const tcu::TextureFormat texFormat         = m_texture->getRefTexture().getFormat();
2083         const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat);
2084 
2085         m_borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.2f, 0.6f, 0.9f, 0.4f));
2086 
2087         m_lookupScale = texFormatInfo.lookupScale;
2088         m_lookupBias  = texFormatInfo.lookupBias;
2089     }
2090 }
2091 
deinit(void)2092 void TextureBorderClampPerAxisCase3D::deinit(void)
2093 {
2094     m_texture.clear();
2095     m_renderer.clear();
2096 }
2097 
iterate(void)2098 TextureBorderClampPerAxisCase3D::IterateResult TextureBorderClampPerAxisCase3D::iterate(void)
2099 {
2100     tcu::Surface renderedFrame(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
2101     const glu::TextureTestUtil::ReferenceParams samplerParams = getSamplerParams();
2102 
2103     logParams(samplerParams);
2104     renderTo(renderedFrame, samplerParams);
2105     verifyImage(renderedFrame, samplerParams);
2106 
2107     return STOP;
2108 }
2109 
logParams(const glu::TextureTestUtil::ReferenceParams & samplerParams)2110 void TextureBorderClampPerAxisCase3D::logParams(const glu::TextureTestUtil::ReferenceParams &samplerParams)
2111 {
2112     const std::string borderColorString =
2113         (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)   ? (de::toString(m_borderColor.get<int32_t>())) :
2114         (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(m_borderColor.get<uint32_t>())) :
2115                                                                         (de::toString(m_borderColor.get<float>()));
2116 
2117     m_testCtx.getLog() << tcu::TestLog::Message << "Border color is " << borderColorString << "\n"
2118                        << "Texture lookup bias: " << samplerParams.colorBias << "\n"
2119                        << "Texture lookup scale: " << samplerParams.colorScale << "\n"
2120                        << "Filter: " << glu::getTextureFilterName(m_filter) << "\n"
2121                        << "Wrap mode: s = " << glu::getRepeatModeStr(m_sWrap)
2122                        << ", t = " << glu::getRepeatModeStr(m_tWrap) << ", r = " << glu::getRepeatModeStr(m_rWrap)
2123                        << "\n"
2124                        << tcu::TestLog::EndMessage;
2125 }
2126 
renderTo(tcu::Surface & surface,const glu::TextureTestUtil::ReferenceParams & samplerParams)2127 void TextureBorderClampPerAxisCase3D::renderTo(tcu::Surface &surface,
2128                                                const glu::TextureTestUtil::ReferenceParams &samplerParams)
2129 {
2130     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2131     const gls::TextureTestUtil::RandomViewport viewport(m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT,
2132                                                         getCaseSeed());
2133 
2134     // Bind to unit 0.
2135     gl.activeTexture(GL_TEXTURE0);
2136     gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture());
2137 
2138     // Setup filtering and wrap modes.
2139     gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS));
2140     gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT));
2141     gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glu::getGLWrapMode(samplerParams.sampler.wrapR));
2142     gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter));
2143     gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter));
2144 
2145     switch (m_channelClass)
2146     {
2147     case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2148     case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2149     case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2150         gl.texParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<float>());
2151         break;
2152 
2153     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2154         gl.texParameterIiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<int32_t>());
2155         break;
2156 
2157     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2158         gl.texParameterIuiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<uint32_t>());
2159         break;
2160 
2161     default:
2162         DE_ASSERT(false);
2163     }
2164 
2165     GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
2166 
2167     gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
2168     m_renderer->renderQuad(0, &m_texCoords[0], samplerParams);
2169     glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess());
2170 }
2171 
verifyImage(const tcu::Surface & renderedFrame,const glu::TextureTestUtil::ReferenceParams & samplerParams)2172 void TextureBorderClampPerAxisCase3D::verifyImage(const tcu::Surface &renderedFrame,
2173                                                   const glu::TextureTestUtil::ReferenceParams &samplerParams)
2174 {
2175     const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
2176     const int colorErrorBits           = 2;
2177     const tcu::IVec4 colorBits =
2178         tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0));
2179     tcu::Surface reference(renderedFrame.getWidth(), renderedFrame.getHeight());
2180     tcu::Surface errorMask(renderedFrame.getWidth(), renderedFrame.getHeight());
2181     tcu::LodPrecision lodPrecision;
2182     tcu::LookupPrecision lookupPrecision;
2183     int numFailedPixels;
2184 
2185     lodPrecision.derivateBits = 18;
2186     lodPrecision.lodBits      = 5;
2187 
2188     lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale;
2189     lookupPrecision.coordBits      = tcu::IVec3(20, 20, 0);
2190     lookupPrecision.uvwBits        = tcu::IVec3(5, 5, 0);
2191     lookupPrecision.colorMask      = glu::TextureTestUtil::getCompareMask(pixelFormat);
2192 
2193     glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(),
2194                                         &m_texCoords[0], samplerParams);
2195 
2196     numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(
2197         renderedFrame.getAccess(), reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(),
2198         &m_texCoords[0], samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog());
2199 
2200     if (numFailedPixels > 0)
2201         m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels
2202                            << " invalid pixels!" << tcu::TestLog::EndMessage;
2203     m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result")
2204                        << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame);
2205     if (numFailedPixels > 0)
2206     {
2207         m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference)
2208                            << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask);
2209     }
2210     m_testCtx.getLog() << tcu::TestLog::EndImageSet;
2211 
2212     if (numFailedPixels == 0)
2213         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2214     else
2215         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
2216 }
2217 
getSamplerParams(void) const2218 glu::TextureTestUtil::ReferenceParams TextureBorderClampPerAxisCase3D::getSamplerParams(void) const
2219 {
2220     const tcu::TextureFormat texFormat = m_texture->getRefTexture().getFormat();
2221     glu::TextureTestUtil::ReferenceParams refParams(glu::TextureTestUtil::TEXTURETYPE_3D);
2222 
2223     refParams.sampler             = glu::mapGLSampler(m_sWrap, m_tWrap, m_rWrap, m_filter, m_filter);
2224     refParams.sampler.borderColor = m_borderColor;
2225     refParams.lodMode             = glu::TextureTestUtil::LODMODE_EXACT;
2226     refParams.samplerType         = glu::TextureTestUtil::getSamplerType(texFormat);
2227     refParams.colorScale          = m_lookupScale;
2228     refParams.colorBias           = m_lookupBias;
2229 
2230     return refParams;
2231 }
2232 
getCaseSeed(void) const2233 uint32_t TextureBorderClampPerAxisCase3D::getCaseSeed(void) const
2234 {
2235     tcu::SeedBuilder builder;
2236     builder << std::string(getName()) << m_texFormat << m_filter << m_sWrap << m_tWrap << m_rWrap
2237             << m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight()
2238             << m_texture->getRefTexture().getDepth();
2239     return builder.get();
2240 }
2241 
isFormatSupported(uint32_t format,bool isGL45)2242 static bool isFormatSupported(uint32_t format, bool isGL45)
2243 {
2244     if (isGL45 && (format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA))
2245         return false;
2246 
2247     return true;
2248 }
2249 
2250 } // namespace
2251 
TextureBorderClampTests(Context & context,bool isGL45)2252 TextureBorderClampTests::TextureBorderClampTests(Context &context, bool isGL45)
2253     : TestCaseGroup(context, "border_clamp", "EXT_texture_border_clamp tests")
2254     , m_isGL45(isGL45)
2255 {
2256 }
2257 
~TextureBorderClampTests(void)2258 TextureBorderClampTests::~TextureBorderClampTests(void)
2259 {
2260 }
2261 
init(void)2262 void TextureBorderClampTests::init(void)
2263 {
2264     static const struct
2265     {
2266         const char *name;
2267         uint32_t filter;
2268         TextureBorderClampTest::SamplingFunction sampling;
2269     } s_filters[] = {
2270         {"nearest", GL_NEAREST, TextureBorderClampTest::SAMPLE_FILTER},
2271         {"linear", GL_LINEAR, TextureBorderClampTest::SAMPLE_FILTER},
2272         {"gather", GL_NEAREST, TextureBorderClampTest::SAMPLE_GATHER},
2273     };
2274 
2275     // .formats
2276     {
2277         static const struct
2278         {
2279             const char *name;
2280             uint32_t format;
2281             tcu::Sampler::DepthStencilMode mode;
2282         } formats[] = {
2283             {"luminance", GL_LUMINANCE, tcu::Sampler::MODE_LAST},
2284             {"alpha", GL_ALPHA, tcu::Sampler::MODE_LAST},
2285             {"luminance_alpha", GL_LUMINANCE_ALPHA, tcu::Sampler::MODE_LAST},
2286             {"bgra", GL_BGRA, tcu::Sampler::MODE_LAST},
2287             {"r8", GL_R8, tcu::Sampler::MODE_LAST},
2288             {"r8_snorm", GL_R8_SNORM, tcu::Sampler::MODE_LAST},
2289             {"rg8", GL_RG8, tcu::Sampler::MODE_LAST},
2290             {"rg8_snorm", GL_RG8_SNORM, tcu::Sampler::MODE_LAST},
2291             {"rgb8", GL_RGB8, tcu::Sampler::MODE_LAST},
2292             {"rgb8_snorm", GL_RGB8_SNORM, tcu::Sampler::MODE_LAST},
2293             {"rgb565", GL_RGB565, tcu::Sampler::MODE_LAST},
2294             {"rgba4", GL_RGBA4, tcu::Sampler::MODE_LAST},
2295             {"rgb5_a1", GL_RGB5_A1, tcu::Sampler::MODE_LAST},
2296             {"rgba8", GL_RGBA8, tcu::Sampler::MODE_LAST},
2297             {"rgba8_snorm", GL_RGBA8_SNORM, tcu::Sampler::MODE_LAST},
2298             {"rgb10_a2", GL_RGB10_A2, tcu::Sampler::MODE_LAST},
2299             {"rgb10_a2ui", GL_RGB10_A2UI, tcu::Sampler::MODE_LAST},
2300             {"srgb8", GL_SRGB8, tcu::Sampler::MODE_LAST},
2301             {"srgb8_alpha8", GL_SRGB8_ALPHA8, tcu::Sampler::MODE_LAST},
2302             {"r16f", GL_R16F, tcu::Sampler::MODE_LAST},
2303             {"rg16f", GL_RG16F, tcu::Sampler::MODE_LAST},
2304             {"rgb16f", GL_RGB16F, tcu::Sampler::MODE_LAST},
2305             {"rgba16f", GL_RGBA16F, tcu::Sampler::MODE_LAST},
2306             {"r32f", GL_R32F, tcu::Sampler::MODE_LAST},
2307             {"rg32f", GL_RG32F, tcu::Sampler::MODE_LAST},
2308             {"rgb32f", GL_RGB32F, tcu::Sampler::MODE_LAST},
2309             {"rgba32f", GL_RGBA32F, tcu::Sampler::MODE_LAST},
2310             {"r11f_g11f_b10f", GL_R11F_G11F_B10F, tcu::Sampler::MODE_LAST},
2311             {"rgb9_e5", GL_RGB9_E5, tcu::Sampler::MODE_LAST},
2312             {"r8i", GL_R8I, tcu::Sampler::MODE_LAST},
2313             {"r8ui", GL_R8UI, tcu::Sampler::MODE_LAST},
2314             {"r16i", GL_R16I, tcu::Sampler::MODE_LAST},
2315             {"r16ui", GL_R16UI, tcu::Sampler::MODE_LAST},
2316             {"r32i", GL_R32I, tcu::Sampler::MODE_LAST},
2317             {"r32ui", GL_R32UI, tcu::Sampler::MODE_LAST},
2318             {"rg8i", GL_RG8I, tcu::Sampler::MODE_LAST},
2319             {"rg8ui", GL_RG8UI, tcu::Sampler::MODE_LAST},
2320             {"rg16i", GL_RG16I, tcu::Sampler::MODE_LAST},
2321             {"rg16ui", GL_RG16UI, tcu::Sampler::MODE_LAST},
2322             {"rg32i", GL_RG32I, tcu::Sampler::MODE_LAST},
2323             {"rg32ui", GL_RG32UI, tcu::Sampler::MODE_LAST},
2324             {"rgb8i", GL_RGB8I, tcu::Sampler::MODE_LAST},
2325             {"rgb8ui", GL_RGB8UI, tcu::Sampler::MODE_LAST},
2326             {"rgb16i", GL_RGB16I, tcu::Sampler::MODE_LAST},
2327             {"rgb16ui", GL_RGB16UI, tcu::Sampler::MODE_LAST},
2328             {"rgb32i", GL_RGB32I, tcu::Sampler::MODE_LAST},
2329             {"rgb32ui", GL_RGB32UI, tcu::Sampler::MODE_LAST},
2330             {"rgba8i", GL_RGBA8I, tcu::Sampler::MODE_LAST},
2331             {"rgba8ui", GL_RGBA8UI, tcu::Sampler::MODE_LAST},
2332             {"rgba16i", GL_RGBA16I, tcu::Sampler::MODE_LAST},
2333             {"rgba16ui", GL_RGBA16UI, tcu::Sampler::MODE_LAST},
2334             {"rgba32i", GL_RGBA32I, tcu::Sampler::MODE_LAST},
2335             {"rgba32ui", GL_RGBA32UI, tcu::Sampler::MODE_LAST},
2336             {"depth_component16", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH},
2337             {"depth_component24", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH},
2338             {"depth_component32f", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH},
2339             {"stencil_index8", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL},
2340             {"depth24_stencil8_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH},
2341             {"depth32f_stencil8_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH},
2342             {"depth24_stencil8_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL},
2343             {"depth32f_stencil8_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL},
2344             {"compressed_r11_eac", GL_COMPRESSED_R11_EAC, tcu::Sampler::MODE_LAST},
2345             {"compressed_signed_r11_eac", GL_COMPRESSED_SIGNED_R11_EAC, tcu::Sampler::MODE_LAST},
2346             {"compressed_rg11_eac", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST},
2347             {"compressed_signed_rg11_eac", GL_COMPRESSED_SIGNED_RG11_EAC, tcu::Sampler::MODE_LAST},
2348             {"compressed_rgb8_etc2", GL_COMPRESSED_RGB8_ETC2, tcu::Sampler::MODE_LAST},
2349             {"compressed_srgb8_etc2", GL_COMPRESSED_SRGB8_ETC2, tcu::Sampler::MODE_LAST},
2350             {"compressed_rgb8_punchthrough_alpha1_etc2", GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
2351              tcu::Sampler::MODE_LAST},
2352             {"compressed_srgb8_punchthrough_alpha1_etc2", GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
2353              tcu::Sampler::MODE_LAST},
2354             {"compressed_rgba8_etc2_eac", GL_COMPRESSED_RGBA8_ETC2_EAC, tcu::Sampler::MODE_LAST},
2355             {"compressed_srgb8_alpha8_etc2_eac", GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, tcu::Sampler::MODE_LAST},
2356         };
2357 
2358         tcu::TestCaseGroup *const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Format tests");
2359         addChild(formatsGroup);
2360 
2361         // .format
2362         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2363         {
2364             const uint32_t format                           = formats[formatNdx].format;
2365             const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode;
2366             const bool isCompressed                         = glu::isCompressedFormat(format);
2367             const bool coreFilterable                       = isCoreFilterableFormat(format, sampleMode);
2368             tcu::TestCaseGroup *const formatGroup =
2369                 new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
2370 
2371             formatsGroup->addChild(formatGroup);
2372 
2373             // .nearest
2374             // .linear
2375             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2376             {
2377                 // [not-compressed]
2378                 // .size_pot
2379                 // .size_npot
2380                 // [compressed]
2381                 // .size_tile_multiple (also pot)
2382                 // .size_not_tile_multiple (also npot)
2383                 for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
2384                 {
2385                     const bool isNpotCase          = (sizeNdx == 1);
2386                     const char *const sizePotName  = (!isCompressed) ? ("size_pot") : ("size_tile_multiple");
2387                     const char *const sizeNpotName = (!isCompressed) ? ("size_npot") : ("size_not_tile_multiple");
2388                     const char *const sizeName     = (isNpotCase) ? (sizeNpotName) : (sizePotName);
2389                     const SizeType sizeType        = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
2390                     const std::string caseName     = std::string() + s_filters[filterNdx].name + "_" + sizeName;
2391                     const uint32_t filter          = s_filters[filterNdx].filter;
2392 
2393                     if ((coreFilterable || !filterRequiresFilterability(filter)) && isFormatSupported(format, m_isGL45))
2394                         formatGroup->addChild(
2395                             new TextureBorderClampFormatCase(m_context, caseName.c_str(), "", format, sampleMode,
2396                                                              TextureBorderClampFormatCase::STATE_TEXTURE_PARAM,
2397                                                              sizeType, filter, s_filters[filterNdx].sampling));
2398                 }
2399             }
2400         }
2401     }
2402 
2403     // .range_clamp
2404     {
2405         static const struct
2406         {
2407             const char *name;
2408             uint32_t format;
2409             tcu::Sampler::DepthStencilMode mode;
2410         } formats[] = {
2411             {"unorm_color", GL_R8, tcu::Sampler::MODE_LAST},
2412             {"snorm_color", GL_R8_SNORM, tcu::Sampler::MODE_LAST},
2413             {"float_color", GL_RG32F, tcu::Sampler::MODE_LAST},
2414             {"int_color", GL_R8I, tcu::Sampler::MODE_LAST},
2415             {"uint_color", GL_R16UI, tcu::Sampler::MODE_LAST},
2416             {"srgb_color", GL_SRGB8_ALPHA8, tcu::Sampler::MODE_LAST},
2417             {"unorm_depth", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH},
2418             {"float_depth", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH},
2419             {"uint_stencil", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL},
2420             {"float_depth_uint_stencil_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH},
2421             {"float_depth_uint_stencil_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL},
2422             {"unorm_depth_uint_stencil_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH},
2423             {"unorm_depth_uint_stencil_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL},
2424             {"compressed_color", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST},
2425         };
2426 
2427         tcu::TestCaseGroup *const rangeClampGroup =
2428             new tcu::TestCaseGroup(m_testCtx, "range_clamp", "Range clamp tests");
2429         addChild(rangeClampGroup);
2430 
2431         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2432             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2433             {
2434                 const uint32_t format                           = formats[formatNdx].format;
2435                 const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode;
2436                 const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + formats[formatNdx].name;
2437                 const uint32_t filter      = s_filters[filterNdx].filter;
2438                 const bool coreFilterable  = isCoreFilterableFormat(format, sampleMode);
2439 
2440                 if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER)
2441                     continue;
2442 
2443                 if (coreFilterable || !filterRequiresFilterability(filter))
2444                     rangeClampGroup->addChild(new TextureBorderClampRangeClampCase(m_context, caseName.c_str(), "",
2445                                                                                    format, sampleMode, filter));
2446             }
2447     }
2448 
2449     // .sampler
2450     {
2451         static const struct
2452         {
2453             const char *name;
2454             uint32_t format;
2455             tcu::Sampler::DepthStencilMode mode;
2456         } formats[] = {
2457             {"unorm_color", GL_R8, tcu::Sampler::MODE_LAST},
2458             {"snorm_color", GL_R8_SNORM, tcu::Sampler::MODE_LAST},
2459             {"float_color", GL_RG32F, tcu::Sampler::MODE_LAST},
2460             {"int_color", GL_R8I, tcu::Sampler::MODE_LAST},
2461             {"uint_color", GL_R16UI, tcu::Sampler::MODE_LAST},
2462             {"unorm_depth", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH},
2463             {"float_depth", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH},
2464             {"uint_stencil", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL},
2465             {"compressed_color", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST},
2466         };
2467 
2468         tcu::TestCaseGroup *const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler param tests");
2469         addChild(samplerGroup);
2470 
2471         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2472         {
2473             const uint32_t format                           = formats[formatNdx].format;
2474             const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode;
2475             const char *caseName                            = formats[formatNdx].name;
2476 
2477             samplerGroup->addChild(new TextureBorderClampFormatCase(
2478                 m_context, caseName, "", format, sampleMode, TextureBorderClampFormatCase::STATE_SAMPLER_PARAM,
2479                 SIZE_POT, GL_NEAREST, TextureBorderClampFormatCase::SAMPLE_FILTER));
2480         }
2481     }
2482 
2483     // .per_axis_wrap_mode
2484     {
2485         static const struct
2486         {
2487             const char *name;
2488             bool is3D;
2489         } targets[] = {
2490             {"texture_2d", false},
2491             {"texture_3d", true},
2492         };
2493         static const struct
2494         {
2495             const char *name;
2496             uint32_t format;
2497             tcu::Sampler::DepthStencilMode mode;
2498             bool supports3D;
2499         } formats[] = {
2500             {"unorm_color", GL_RG8, tcu::Sampler::MODE_LAST, true},
2501             {"snorm_color", GL_RG8_SNORM, tcu::Sampler::MODE_LAST, true},
2502             {"float_color", GL_R32F, tcu::Sampler::MODE_LAST, true},
2503             {"int_color", GL_RG16I, tcu::Sampler::MODE_LAST, true},
2504             {"uint_color", GL_R8UI, tcu::Sampler::MODE_LAST, true},
2505             {"unorm_depth", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH, false},
2506             {"float_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH, false},
2507             {"uint_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL, false},
2508             {"compressed_color", GL_COMPRESSED_RGB8_ETC2, tcu::Sampler::MODE_LAST, false},
2509         };
2510         static const struct
2511         {
2512             const char *name;
2513             uint32_t sWrap;
2514             uint32_t tWrap;
2515             uint32_t rWrap;
2516             bool is3D;
2517         } wrapConfigs[] = {
2518             // 2d configs
2519             {"s_clamp_to_edge_t_clamp_to_border", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_NONE, false},
2520             {"s_repeat_t_clamp_to_border", GL_REPEAT, GL_CLAMP_TO_BORDER, GL_NONE, false},
2521             {"s_mirrored_repeat_t_clamp_to_border", GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, GL_NONE, false},
2522 
2523             // 3d configs
2524             {"s_clamp_to_border_t_clamp_to_border_r_clamp_to_border", GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER,
2525              GL_CLAMP_TO_BORDER, true},
2526             {"s_clamp_to_border_t_clamp_to_border_r_repeat", GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, GL_REPEAT, true},
2527             {"s_mirrored_repeat_t_clamp_to_border_r_repeat", GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, GL_REPEAT, true},
2528             {"s_repeat_t_mirrored_repeat_r_clamp_to_border", GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, true},
2529         };
2530 
2531         tcu::TestCaseGroup *const perAxisGroup =
2532             new tcu::TestCaseGroup(m_testCtx, "per_axis_wrap_mode", "Per-axis wrapping modes");
2533         addChild(perAxisGroup);
2534 
2535         // .texture_nd
2536         for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx)
2537         {
2538             tcu::TestCaseGroup *const targetGroup =
2539                 new tcu::TestCaseGroup(m_testCtx, targets[targetNdx].name, "Texture target test");
2540             perAxisGroup->addChild(targetGroup);
2541 
2542             // .format
2543             for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2544             {
2545                 if (targets[targetNdx].is3D && !formats[formatNdx].supports3D)
2546                     continue;
2547                 else
2548                 {
2549                     const uint32_t format                           = formats[formatNdx].format;
2550                     const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode;
2551                     const bool coreFilterable                       = isCoreFilterableFormat(format, sampleMode);
2552                     tcu::TestCaseGroup *const formatGroup =
2553                         new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
2554                     targetGroup->addChild(formatGroup);
2555 
2556                     // .linear
2557                     // .nearest
2558                     // .gather
2559                     for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2560                     {
2561                         const uint32_t filter = s_filters[filterNdx].filter;
2562 
2563                         if (!coreFilterable && filterRequiresFilterability(filter))
2564                         {
2565                             // skip linear on pure integers
2566                             continue;
2567                         }
2568                         else if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER &&
2569                                  targets[targetNdx].is3D)
2570                         {
2571                             // skip gather on 3d
2572                             continue;
2573                         }
2574                         else
2575                         {
2576                             tcu::TestCaseGroup *const filteringGroup = new tcu::TestCaseGroup(
2577                                 m_testCtx, s_filters[filterNdx].name, "Tests with specific filter");
2578                             formatGroup->addChild(filteringGroup);
2579 
2580                             // .s_XXX_t_XXX(_r_XXX)
2581                             for (int wrapNdx = 0; wrapNdx < DE_LENGTH_OF_ARRAY(wrapConfigs); ++wrapNdx)
2582                             {
2583                                 if (wrapConfigs[wrapNdx].is3D != targets[targetNdx].is3D)
2584                                     continue;
2585                                 else
2586                                 {
2587                                     for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
2588                                     {
2589                                         const char *const wrapName          = wrapConfigs[wrapNdx].name;
2590                                         const bool isNpotCase               = (sizeNdx == 1);
2591                                         const char *const sizeNameExtension = (isNpotCase) ? ("_npot") : ("_pot");
2592                                         const SizeType size                 = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
2593 
2594                                         if (!targets[targetNdx].is3D)
2595                                             filteringGroup->addChild(new TextureBorderClampPerAxisCase2D(
2596                                                 m_context, (std::string() + wrapName + sizeNameExtension).c_str(), "",
2597                                                 format, sampleMode, size, filter, wrapConfigs[wrapNdx].sWrap,
2598                                                 wrapConfigs[wrapNdx].tWrap, s_filters[filterNdx].sampling));
2599                                         else
2600                                         {
2601                                             DE_ASSERT(sampleMode == tcu::Sampler::MODE_LAST);
2602                                             filteringGroup->addChild(new TextureBorderClampPerAxisCase3D(
2603                                                 m_context, (std::string() + wrapName + sizeNameExtension).c_str(), "",
2604                                                 format, size, filter, wrapConfigs[wrapNdx].sWrap,
2605                                                 wrapConfigs[wrapNdx].tWrap, wrapConfigs[wrapNdx].rWrap));
2606                                         }
2607                                     }
2608                                 }
2609                             }
2610                         }
2611                     }
2612                 }
2613             }
2614         }
2615     }
2616 
2617     // .depth_compare_mode
2618     {
2619         static const struct
2620         {
2621             const char *name;
2622             uint32_t format;
2623         } formats[] = {
2624             {"depth_component16", GL_DEPTH_COMPONENT16},
2625             {"depth_component24", GL_DEPTH_COMPONENT24},
2626             {"depth24_stencil8", GL_DEPTH24_STENCIL8},
2627             {"depth32f_stencil8", GL_DEPTH32F_STENCIL8},
2628         };
2629 
2630         tcu::TestCaseGroup *const compareGroup =
2631             new tcu::TestCaseGroup(m_testCtx, "depth_compare_mode", "Tests depth compare mode");
2632         addChild(compareGroup);
2633 
2634         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2635         {
2636             const uint32_t format = formats[formatNdx].format;
2637             tcu::TestCaseGroup *const formatGroup =
2638                 new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test");
2639 
2640             compareGroup->addChild(formatGroup);
2641 
2642             // (format).(linear|nearest|gather)_(pot|npot)
2643             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx)
2644                 for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx)
2645                 {
2646                     const bool isNpotCase      = (sizeNdx == 1);
2647                     const char *const sizeName = (isNpotCase) ? ("size_npot") : ("size_pot");
2648                     const SizeType sizeType    = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT);
2649                     const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + sizeName;
2650                     const uint32_t filter      = s_filters[filterNdx].filter;
2651 
2652                     formatGroup->addChild(new TextureBorderClampDepthCompareCase(
2653                         m_context, caseName.c_str(), "", format, sizeType, filter, s_filters[filterNdx].sampling));
2654                 }
2655         }
2656     }
2657 
2658     // unused channels (A in rgb, G in stencil etc.)
2659     {
2660         static const struct
2661         {
2662             const char *name;
2663             uint32_t format;
2664             tcu::Sampler::DepthStencilMode mode;
2665         } formats[] = {
2666             {"r8", GL_R8, tcu::Sampler::MODE_LAST},
2667             {"rg8_snorm", GL_RG8_SNORM, tcu::Sampler::MODE_LAST},
2668             {"rgb8", GL_RGB8, tcu::Sampler::MODE_LAST},
2669             {"rg32f", GL_RG32F, tcu::Sampler::MODE_LAST},
2670             {"r16i", GL_RG16I, tcu::Sampler::MODE_LAST},
2671             {"luminance", GL_LUMINANCE, tcu::Sampler::MODE_LAST},
2672             {"alpha", GL_ALPHA, tcu::Sampler::MODE_LAST},
2673             {"luminance_alpha", GL_LUMINANCE_ALPHA, tcu::Sampler::MODE_LAST},
2674             {"depth_component16", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH},
2675             {"depth_component32f", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH},
2676             {"stencil_index8", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL},
2677             {"depth32f_stencil8_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH},
2678             {"depth32f_stencil8_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL},
2679             {"depth24_stencil8_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH},
2680             {"depth24_stencil8_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL},
2681             {"compressed_r11_eac", GL_COMPRESSED_R11_EAC, tcu::Sampler::MODE_LAST},
2682         };
2683 
2684         tcu::TestCaseGroup *const unusedGroup = new tcu::TestCaseGroup(
2685             m_testCtx, "unused_channels", "Tests channels that are not present in the internal format");
2686         addChild(unusedGroup);
2687 
2688         for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
2689         {
2690             if (isFormatSupported(formats[formatNdx].format, m_isGL45))
2691             {
2692                 unusedGroup->addChild(new TextureBorderClampUnusedChannelCase(
2693                     m_context, formats[formatNdx].name, "", formats[formatNdx].format, formats[formatNdx].mode));
2694             }
2695         }
2696     }
2697 }
2698 
2699 } // namespace Functional
2700 } // namespace gles31
2701 } // namespace deqp
2702