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