Fix PIPELINE_STAGE_TOP_OF_PIPE_BIT usage in api tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fTextureFilteringTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Texture filtering tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fTextureFilteringTests.hpp"
25
26 #include "glsTextureTestUtil.hpp"
27
28 #include "gluPixelTransfer.hpp"
29 #include "gluTexture.hpp"
30 #include "gluTextureUtil.hpp"
31
32 #include "tcuCommandLine.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuTexLookupVerifier.hpp"
36 #include "tcuVectorUtil.hpp"
37
38 #include "deStringUtil.hpp"
39 #include "deString.h"
40
41 #include "glwFunctions.hpp"
42 #include "glwEnums.hpp"
43
44 namespace deqp
45 {
46 namespace gles31
47 {
48 namespace Functional
49 {
50
51 using std::vector;
52 using std::string;
53 using tcu::TestLog;
54 using namespace gls::TextureTestUtil;
55 using namespace glu::TextureTestUtil;
56
57 static const char* getFaceDesc (const tcu::CubeFace face)
58 {
59         switch (face)
60         {
61                 case tcu::CUBEFACE_NEGATIVE_X:  return "-X";
62                 case tcu::CUBEFACE_POSITIVE_X:  return "+X";
63                 case tcu::CUBEFACE_NEGATIVE_Y:  return "-Y";
64                 case tcu::CUBEFACE_POSITIVE_Y:  return "+Y";
65                 case tcu::CUBEFACE_NEGATIVE_Z:  return "-Z";
66                 case tcu::CUBEFACE_POSITIVE_Z:  return "+Z";
67                 default:
68                         DE_ASSERT(false);
69                         return DE_NULL;
70         }
71 }
72
73 static void logCubeArrayTexCoords(TestLog& log, vector<float>& texCoord)
74 {
75         const size_t numVerts = texCoord.size() / 4;
76
77         DE_ASSERT(texCoord.size() % 4 == 0);
78
79         for (size_t vertNdx = 0; vertNdx < numVerts; vertNdx++)
80         {
81                 const size_t    coordNdx        = vertNdx * 4;
82
83                 const float             u                       = texCoord[coordNdx + 0];
84                 const float             v                       = texCoord[coordNdx + 1];
85                 const float             w                       = texCoord[coordNdx + 2];
86                 const float             q                       = texCoord[coordNdx + 3];
87
88                 log << TestLog::Message
89                         << vertNdx << ": ("
90                         << u << ", "
91                         << v << ", "
92                         << w << ", "
93                         << q << ")"
94                         << TestLog::EndMessage;
95         }
96 }
97
98 // Cube map array filtering
99
100 class TextureCubeArrayFilteringCase : public TestCase
101 {
102 public:
103                                                                         TextureCubeArrayFilteringCase   (Context& context,
104                                                                                                                                          const char* name,
105                                                                                                                                          const char* desc,
106                                                                                                                                          deUint32 minFilter,
107                                                                                                                                          deUint32 magFilter,
108                                                                                                                                          deUint32 wrapS,
109                                                                                                                                          deUint32 wrapT,
110                                                                                                                                          deUint32 internalFormat,
111                                                                                                                                          int size,
112                                                                                                                                          int depth,
113                                                                                                                                          bool onlySampleFaceInterior = false);
114
115                                                                         ~TextureCubeArrayFilteringCase  (void);
116
117         void                                                    init                                                    (void);
118         void                                                    deinit                                                  (void);
119         IterateResult                                   iterate                                                 (void);
120
121 private:
122                                                                         TextureCubeArrayFilteringCase   (const TextureCubeArrayFilteringCase&);
123         TextureCubeArrayFilteringCase&  operator=                                               (const TextureCubeArrayFilteringCase&);
124
125         const deUint32                                  m_minFilter;
126         const deUint32                                  m_magFilter;
127         const deUint32                                  m_wrapS;
128         const deUint32                                  m_wrapT;
129
130         const deUint32                                  m_internalFormat;
131         const int                                               m_size;
132         const int                                               m_depth;
133
134         const bool                                              m_onlySampleFaceInterior; //!< If true, we avoid sampling anywhere near a face's edges.
135
136         struct FilterCase
137         {
138                 const glu::TextureCubeArray*    texture;
139                 tcu::Vec2                                               bottomLeft;
140                 tcu::Vec2                                               topRight;
141                 tcu::Vec2                                               layerRange;
142
143                 FilterCase (void)
144                         : texture(DE_NULL)
145                 {
146                 }
147
148                 FilterCase (const glu::TextureCubeArray* tex_, const tcu::Vec2& bottomLeft_, const tcu::Vec2& topRight_, const tcu::Vec2& layerRange_)
149                         : texture               (tex_)
150                         , bottomLeft    (bottomLeft_)
151                         , topRight              (topRight_)
152                         , layerRange    (layerRange_)
153                 {
154                 }
155         };
156
157         glu::TextureCubeArray*  m_gradientTex;
158         glu::TextureCubeArray*  m_gridTex;
159
160         TextureRenderer                 m_renderer;
161
162         std::vector<FilterCase> m_cases;
163         int                                             m_caseNdx;
164 };
165
166 TextureCubeArrayFilteringCase::TextureCubeArrayFilteringCase (Context& context,
167                                                                                                                           const char* name,
168                                                                                                                           const char* desc,
169                                                                                                                           deUint32 minFilter,
170                                                                                                                           deUint32 magFilter,
171                                                                                                                           deUint32 wrapS,
172                                                                                                                           deUint32 wrapT,
173                                                                                                                           deUint32 internalFormat,
174                                                                                                                           int size,
175                                                                                                                           int depth,
176                                                                                                                           bool onlySampleFaceInterior)
177         : TestCase                                      (context, name, desc)
178         , m_minFilter                           (minFilter)
179         , m_magFilter                           (magFilter)
180         , m_wrapS                                       (wrapS)
181         , m_wrapT                                       (wrapT)
182         , m_internalFormat                      (internalFormat)
183         , m_size                                        (size)
184         , m_depth                                       (depth)
185         , m_onlySampleFaceInterior      (onlySampleFaceInterior)
186         , m_gradientTex                         (DE_NULL)
187         , m_gridTex                                     (DE_NULL)
188         , m_renderer                            (context.getRenderContext(), context.getTestContext().getLog(), glu::GLSL_VERSION_310_ES, glu::PRECISION_HIGHP)
189         , m_caseNdx                                     (0)
190 {
191 }
192
193 TextureCubeArrayFilteringCase::~TextureCubeArrayFilteringCase (void)
194 {
195         TextureCubeArrayFilteringCase::deinit();
196 }
197
198 void TextureCubeArrayFilteringCase::init (void)
199 {
200         const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
201
202         if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_cube_map_array"))
203                 throw tcu::NotSupportedError("GL_EXT_texture_cube_map_array not supported");
204
205         if (m_internalFormat == GL_SR8_EXT && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")))
206                 TCU_THROW(NotSupportedError, "GL_EXT_texture_sRGB_R8 not supported");
207
208         try
209         {
210                 const tcu::TextureFormat                texFmt          = glu::mapGLInternalFormat(m_internalFormat);
211                 const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(texFmt);
212                 const tcu::Vec4                                 cScale          = fmtInfo.valueMax-fmtInfo.valueMin;
213                 const tcu::Vec4                                 cBias           = fmtInfo.valueMin;
214                 const int                                               numLevels       = deLog2Floor32(m_size) + 1;
215                 const int                                               numLayers       = m_depth / 6;
216
217                 // Create textures.
218                 m_gradientTex   = new glu::TextureCubeArray(m_context.getRenderContext(), m_internalFormat, m_size, m_depth);
219                 m_gridTex               = new glu::TextureCubeArray(m_context.getRenderContext(), m_internalFormat, m_size, m_depth);
220
221                 const tcu::IVec4 levelSwz[] =
222                 {
223                         tcu::IVec4(0,1,2,3),
224                         tcu::IVec4(2,1,3,0),
225                         tcu::IVec4(3,0,1,2),
226                         tcu::IVec4(1,3,2,0),
227                 };
228
229                 // Fill first gradient texture (gradient direction varies between layers).
230                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
231                 {
232                         m_gradientTex->getRefTexture().allocLevel(levelNdx);
233
234                         const tcu::PixelBufferAccess levelBuf = m_gradientTex->getRefTexture().getLevel(levelNdx);
235
236                         for (int layerFaceNdx = 0; layerFaceNdx < m_depth; layerFaceNdx++)
237                         {
238                                 const tcu::IVec4        swz             = levelSwz[layerFaceNdx % DE_LENGTH_OF_ARRAY(levelSwz)];
239                                 const tcu::Vec4         gMin    = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
240                                 const tcu::Vec4         gMax    = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f).swizzle(swz[0],swz[1],swz[2],swz[3])*cScale + cBias;
241
242                                 tcu::fillWithComponentGradients(tcu::getSubregion(levelBuf, 0, 0, layerFaceNdx, levelBuf.getWidth(), levelBuf.getHeight(), 1), gMin, gMax);
243                         }
244                 }
245
246                 // Fill second with grid texture (each layer has unique colors).
247                 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
248                 {
249                         m_gridTex->getRefTexture().allocLevel(levelNdx);
250
251                         const tcu::PixelBufferAccess levelBuf = m_gridTex->getRefTexture().getLevel(levelNdx);
252
253                         for (int layerFaceNdx = 0; layerFaceNdx < m_depth; layerFaceNdx++)
254                         {
255                                 const deUint32  step    = 0x00ffffff / (numLevels*m_depth - 1);
256                                 const deUint32  rgb             = step * (levelNdx + layerFaceNdx*numLevels);
257                                 const deUint32  colorA  = 0xff000000 | rgb;
258                                 const deUint32  colorB  = 0xff000000 | ~rgb;
259
260                                 tcu::fillWithGrid(tcu::getSubregion(levelBuf, 0, 0, layerFaceNdx, levelBuf.getWidth(), levelBuf.getHeight(), 1),
261                                                                   4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
262                         }
263                 }
264
265                 // Upload.
266                 m_gradientTex->upload();
267                 m_gridTex->upload();
268
269                 // Test cases
270                 {
271                         const glu::TextureCubeArray* const      tex0    = m_gradientTex;
272                         const glu::TextureCubeArray* const      tex1    = m_gridTex;
273
274                         if (m_onlySampleFaceInterior)
275                         {
276                                 m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f),     tcu::Vec2(0.8f,  0.8f), tcu::Vec2(-0.5f, float(numLayers)+0.5f)));      // minification
277                                 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f),      tcu::Vec2(0.8f,  0.8f), tcu::Vec2(-0.5f, float(numLayers)+0.5f)));      // magnification
278                                 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f),     tcu::Vec2(0.8f,  0.8f), tcu::Vec2(float(numLayers)+0.5f, -0.5f)));      // minification
279                                 m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f),       tcu::Vec2(0.6f,  0.5f), tcu::Vec2(float(numLayers)+0.5f, -0.5f)));      // magnification
280                         }
281                         else
282                         {
283                                 const bool isSingleSample = (m_context.getRenderTarget().getNumSamples() == 0);
284
285                                 // minification - w/ tweak to avoid hitting triangle edges with a face switchpoint in multisample configs
286                                 if (isSingleSample)
287                                         m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f), tcu::Vec2(-0.5f, float(numLayers)+0.5f)));
288                                 else
289                                         m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f), tcu::Vec2(-0.5f, float(numLayers)+0.5f)));
290
291                                 m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f),               tcu::Vec2(1.25f, 1.20f),        tcu::Vec2(-0.5f, float(numLayers)+0.5f)));      // magnification
292                                 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f),    tcu::Vec2(1.1f, 1.35f),         tcu::Vec2(float(numLayers)+0.5f, -0.5f)));      // minification
293                                 m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f),             tcu::Vec2(-0.8f, -0.8f),        tcu::Vec2(float(numLayers)+0.5f, -0.5f)));      // magnification
294
295                                 // Layer rounding - only in single-sample configs as multisample configs may produce smooth transition at the middle.
296                                 if (isSingleSample && (numLayers > 1))
297                                         m_cases.push_back(FilterCase(tex0,      tcu::Vec2(-2.0f, -1.5f  ),      tcu::Vec2(-0.1f,  0.9f), tcu::Vec2(1.50001f, 1.49999f)));
298                         }
299                 }
300
301                 m_caseNdx = 0;
302                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
303         }
304         catch (...)
305         {
306                 // Clean up to save memory.
307                 TextureCubeArrayFilteringCase::deinit();
308                 throw;
309         }
310 }
311
312 void TextureCubeArrayFilteringCase::deinit (void)
313 {
314         delete m_gradientTex;
315         delete m_gridTex;
316
317         m_gradientTex   = DE_NULL;
318         m_gridTex               = DE_NULL;
319
320         m_renderer.clear();
321         m_cases.clear();
322 }
323
324 TextureCubeArrayFilteringCase::IterateResult TextureCubeArrayFilteringCase::iterate (void)
325 {
326         TestLog&                                                log                             = m_testCtx.getLog();
327         const glu::RenderContext&               renderCtx               = m_context.getRenderContext();
328         const glw::Functions&                   gl                              = renderCtx.getFunctions();
329         const int                                               viewportSize    = 28;
330         const deUint32                                  randomSeed              = deStringHash(getName()) ^ deInt32Hash(m_caseNdx) ^ m_testCtx.getCommandLine().getBaseSeed();
331         const RandomViewport                    viewport                (m_context.getRenderTarget(), viewportSize, viewportSize, randomSeed);
332         const FilterCase&                               curCase                 = m_cases[m_caseNdx];
333         const tcu::TextureFormat                texFmt                  = curCase.texture->getRefTexture().getFormat();
334         const tcu::TextureFormatInfo    fmtInfo                 = tcu::getTextureFormatInfo(texFmt);
335         const tcu::ScopedLogSection             section                 (m_testCtx.getLog(), string("Test") + de::toString(m_caseNdx), string("Test ") + de::toString(m_caseNdx));
336         ReferenceParams                                 refParams               (TEXTURETYPE_CUBE_ARRAY);
337
338         if (viewport.width < viewportSize || viewport.height < viewportSize)
339                 throw tcu::NotSupportedError("Render target too small", "", __FILE__, __LINE__);
340
341         // Params for reference computation.
342         refParams.sampler                                       = glu::mapGLSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, m_minFilter, m_magFilter);
343         refParams.sampler.seamlessCubeMap       = true;
344         refParams.samplerType                           = getSamplerType(texFmt);
345         refParams.colorBias                                     = fmtInfo.lookupBias;
346         refParams.colorScale                            = fmtInfo.lookupScale;
347         refParams.lodMode                                       = LODMODE_EXACT;
348
349         gl.bindTexture  (GL_TEXTURE_CUBE_MAP_ARRAY, curCase.texture->getGLTexture());
350         gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER,      m_minFilter);
351         gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER,      m_magFilter);
352         gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S,          m_wrapS);
353         gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T,          m_wrapT);
354
355         gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
356
357         m_testCtx.getLog() << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight << TestLog::EndMessage;
358
359         for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
360         {
361                 const tcu::CubeFace             face            = tcu::CubeFace(faceNdx);
362                 tcu::Surface                    result          (viewport.width, viewport.height);
363                 vector<float>                   texCoord;
364
365                 computeQuadTexCoordCubeArray(texCoord, face, curCase.bottomLeft, curCase.topRight, curCase.layerRange);
366
367                 log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
368
369                 log << TestLog::Message << "Texture coordinates:" << TestLog::EndMessage;
370
371                 logCubeArrayTexCoords(log, texCoord);
372
373                 m_renderer.renderQuad(0, &texCoord[0], refParams);
374                 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
375
376                 glu::readPixels(renderCtx, viewport.x, viewport.y, result.getAccess());
377                 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
378
379                 {
380                         const bool                              isNearestOnly   = m_minFilter == GL_NEAREST && m_magFilter == GL_NEAREST;
381                         const tcu::PixelFormat  pixelFormat             = renderCtx.getRenderTarget().getPixelFormat();
382                         const tcu::IVec4                coordBits               = tcu::IVec4(10);
383                         const tcu::IVec4                colorBits               = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2), tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
384                         tcu::LodPrecision               lodPrecision;
385                         tcu::LookupPrecision    lookupPrecision;
386
387                         lodPrecision.derivateBits               = 10;
388                         lodPrecision.lodBits                    = 5;
389                         lookupPrecision.colorThreshold  = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
390                         lookupPrecision.coordBits               = coordBits.toWidth<3>();
391                         lookupPrecision.uvwBits                 = tcu::IVec3(6);
392                         lookupPrecision.colorMask               = getCompareMask(pixelFormat);
393
394                         const bool isHighQuality = verifyTextureResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(),
395                                                                                                                    &texCoord[0], refParams, lookupPrecision, coordBits, lodPrecision, pixelFormat);
396
397                         if (!isHighQuality)
398                         {
399                                 // Evaluate against lower precision requirements.
400                                 lodPrecision.lodBits    = 4;
401                                 lookupPrecision.uvwBits = tcu::IVec3(4);
402
403                                 m_testCtx.getLog() << TestLog::Message << "Warning: Verification against high precision requirements failed, trying with lower requirements." << TestLog::EndMessage;
404
405                                 const bool isOk = verifyTextureResult(m_testCtx, result.getAccess(), curCase.texture->getRefTexture(),
406                                                                                                           &texCoord[0], refParams, lookupPrecision, coordBits, lodPrecision, pixelFormat);
407
408                                 if (!isOk)
409                                 {
410                                         m_testCtx.getLog() << TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << TestLog::EndMessage;
411                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
412                                 }
413                                 else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
414                                         m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality filtering result");
415                         }
416                 }
417         }
418
419         m_caseNdx += 1;
420         return m_caseNdx < (int)m_cases.size() ? CONTINUE : STOP;
421 }
422
423 TextureFilteringTests::TextureFilteringTests (Context& context)
424         : TestCaseGroup(context, "filtering", "Texture Filtering Tests")
425 {
426 }
427
428 TextureFilteringTests::~TextureFilteringTests (void)
429 {
430 }
431
432 void TextureFilteringTests::init (void)
433 {
434         static const struct
435         {
436                 const char*             name;
437                 deUint32                mode;
438         } wrapModes[] =
439         {
440                 { "clamp",              GL_CLAMP_TO_EDGE },
441                 { "repeat",             GL_REPEAT },
442                 { "mirror",             GL_MIRRORED_REPEAT }
443         };
444
445         static const struct
446         {
447                 const char*             name;
448                 deUint32                mode;
449         } minFilterModes[] =
450         {
451                 { "nearest",                            GL_NEAREST                                      },
452                 { "linear",                                     GL_LINEAR                                       },
453                 { "nearest_mipmap_nearest",     GL_NEAREST_MIPMAP_NEAREST       },
454                 { "linear_mipmap_nearest",      GL_LINEAR_MIPMAP_NEAREST        },
455                 { "nearest_mipmap_linear",      GL_NEAREST_MIPMAP_LINEAR        },
456                 { "linear_mipmap_linear",       GL_LINEAR_MIPMAP_LINEAR         }
457         };
458
459         static const struct
460         {
461                 const char*             name;
462                 deUint32                mode;
463         } magFilterModes[] =
464         {
465                 { "nearest",    GL_NEAREST },
466                 { "linear",             GL_LINEAR }
467         };
468
469         static const struct
470         {
471                 int size;
472                 int depth;
473         } sizesCubeArray[] =
474         {
475                 {   8,   6 },
476                 {  64,  12 },
477                 { 128,  12 },
478                 {   7,  12 },
479                 {  63,  18 }
480         };
481
482         static const struct
483         {
484                 const char*             name;
485                 deUint32                format;
486         } filterableFormatsByType[] =
487         {
488                 { "rgba16f",            GL_RGBA16F                      },
489                 { "r11f_g11f_b10f",     GL_R11F_G11F_B10F       },
490                 { "rgb9_e5",            GL_RGB9_E5                      },
491                 { "rgba8",                      GL_RGBA8                        },
492                 { "rgba8_snorm",        GL_RGBA8_SNORM          },
493                 { "rgb565",                     GL_RGB565                       },
494                 { "rgba4",                      GL_RGBA4                        },
495                 { "rgb5_a1",            GL_RGB5_A1                      },
496                 { "sr8",                        GL_SR8_EXT                      },
497                 { "srgb8_alpha8",       GL_SRGB8_ALPHA8         },
498                 { "rgb10_a2",           GL_RGB10_A2                     }
499         };
500
501         // Cube map array texture filtering.
502         {
503                 tcu::TestCaseGroup* const groupCubeArray = new tcu::TestCaseGroup(m_testCtx, "cube_array", "Cube Map Array Texture Filtering");
504                 addChild(groupCubeArray);
505
506                 // Formats.
507                 {
508                         tcu::TestCaseGroup* const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Cube Map Array Texture Formats");
509                         groupCubeArray->addChild(formatsGroup);
510
511                         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
512                         {
513                                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
514                                 {
515                                         const deUint32  minFilter       = minFilterModes[filterNdx].mode;
516                                         const char*             filterName      = minFilterModes[filterNdx].name;
517                                         const deUint32  format          = filterableFormatsByType[fmtNdx].format;
518                                         const char*             formatName      = filterableFormatsByType[fmtNdx].name;
519                                         const bool              isMipmap        = minFilter != GL_NEAREST && minFilter != GL_LINEAR;
520                                         const deUint32  magFilter       = isMipmap ? GL_LINEAR : minFilter;
521                                         const string    name            = string(formatName) + "_" + filterName;
522                                         const deUint32  wrapS           = GL_REPEAT;
523                                         const deUint32  wrapT           = GL_REPEAT;
524                                         const int               size            = 64;
525                                         const int               depth           = 12;
526
527                                         formatsGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
528                                                                                                                                                          name.c_str(), "",
529                                                                                                                                                          minFilter, magFilter,
530                                                                                                                                                          wrapS, wrapT,
531                                                                                                                                                          format,
532                                                                                                                                                          size, depth));
533                                 }
534                         }
535                 }
536
537                 // Sizes.
538                 {
539                         tcu::TestCaseGroup* const sizesGroup = new tcu::TestCaseGroup(m_testCtx, "sizes", "Texture Sizes");
540                         groupCubeArray->addChild(sizesGroup);
541
542                         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCubeArray); sizeNdx++)
543                         {
544                                 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
545                                 {
546                                         const deUint32  minFilter       = minFilterModes[filterNdx].mode;
547                                         const char*             filterName      = minFilterModes[filterNdx].name;
548                                         const deUint32  format          = GL_RGBA8;
549                                         const bool              isMipmap        = minFilter != GL_NEAREST && minFilter != GL_LINEAR;
550                                         const deUint32  magFilter       = isMipmap ? GL_LINEAR : minFilter;
551                                         const deUint32  wrapS           = GL_REPEAT;
552                                         const deUint32  wrapT           = GL_REPEAT;
553                                         const int               size            = sizesCubeArray[sizeNdx].size;
554                                         const int               depth           = sizesCubeArray[sizeNdx].depth;
555                                         const string    name            = de::toString(size) + "x" + de::toString(size) + "x" + de::toString(depth) + "_" + filterName;
556
557                                         sizesGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
558                                                                                                                                                    name.c_str(), "",
559                                                                                                                                                    minFilter, magFilter,
560                                                                                                                                                    wrapS, wrapT,
561                                                                                                                                                    format,
562                                                                                                                                                    size, depth));
563                                 }
564                         }
565                 }
566
567                 // Wrap modes.
568                 {
569                         tcu::TestCaseGroup* const combinationsGroup = new tcu::TestCaseGroup(m_testCtx, "combinations", "Filter and wrap mode combinations");
570                         groupCubeArray->addChild(combinationsGroup);
571
572                         for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
573                         {
574                                 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
575                                 {
576                                         for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
577                                         {
578                                                 for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
579                                                 {
580                                                         const deUint32  minFilter       = minFilterModes[minFilterNdx].mode;
581                                                         const deUint32  magFilter       = magFilterModes[magFilterNdx].mode;
582                                                         const deUint32  format          = GL_RGBA8;
583                                                         const deUint32  wrapS           = wrapModes[wrapSNdx].mode;
584                                                         const deUint32  wrapT           = wrapModes[wrapTNdx].mode;
585                                                         const int               size            = 63;
586                                                         const int               depth           = 12;
587                                                         const string    name            = string(minFilterModes[minFilterNdx].name) + "_" + magFilterModes[magFilterNdx].name + "_" + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
588
589                                                         combinationsGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
590                                                                                                                                                                                   name.c_str(), "",
591                                                                                                                                                                                   minFilter, magFilter,
592                                                                                                                                                                                   wrapS, wrapT,
593                                                                                                                                                                                   format,
594                                                                                                                                                                                   size, depth));
595                                                 }
596                                         }
597                                 }
598                         }
599                 }
600
601                 // Cases with no visible cube edges.
602                 {
603                         tcu::TestCaseGroup* const onlyFaceInteriorGroup = new tcu::TestCaseGroup(m_testCtx, "no_edges_visible", "Don't sample anywhere near a face's edges");
604                         groupCubeArray->addChild(onlyFaceInteriorGroup);
605
606                         for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
607                         {
608                                 const bool              isLinear        = isLinearI != 0;
609                                 const deUint32  filter          = isLinear ? GL_LINEAR : GL_NEAREST;
610
611                                 onlyFaceInteriorGroup->addChild(new TextureCubeArrayFilteringCase(m_context,
612                                                                                                                                                                   isLinear ? "linear" : "nearest", "",
613                                                                                                                                                                   filter, filter,
614                                                                                                                                                                   GL_REPEAT, GL_REPEAT,
615                                                                                                                                                                   GL_RGBA8,
616                                                                                                                                                                   63, 12,
617                                                                                                                                                                   true));
618                         }
619                 }
620         }
621 }
622
623 } // Functional
624 } // gles31
625 } // deqp