Add new framebuffer fetch extension tests am: 2a609fb223
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / functional / es2fDefaultVertexAttributeTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Default vertex attribute test
22  *//*--------------------------------------------------------------------*/
23
24 #include "es2fDefaultVertexAttributeTests.hpp"
25 #include "tcuVector.hpp"
26 #include "tcuRenderTarget.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuTextureUtil.hpp"
29 #include "gluRenderContext.hpp"
30 #include "gluCallLogWrapper.hpp"
31 #include "gluShaderProgram.hpp"
32 #include "gluObjectWrapper.hpp"
33 #include "gluPixelTransfer.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "deMath.h"
37 #include "deStringUtil.hpp"
38 #include "deString.h"
39
40 #include <limits>
41
42 namespace deqp
43 {
44 namespace gles2
45 {
46 namespace Functional
47 {
48 namespace
49 {
50
51 static const int s_valueRange = 10;
52
53 static const char* const s_passThroughFragmentShaderSource =    "varying mediump vec4 v_color;\n"
54                                                                                                                                 "void main (void)\n"
55                                                                                                                                 "{\n"
56                                                                                                                                 "       gl_FragColor = v_color;\n"
57                                                                                                                                 "}\n";
58
59 template <typename T1, int S1, typename T2, int S2>
60 tcu::Vector<T1, S1> convertToTypeVec (const tcu::Vector<T2, S2>& v)
61 {
62         tcu::Vector<T1, S1> retVal;
63
64         for (int ndx = 0; ndx < S1; ++ndx)
65                 retVal[ndx] = T1(0);
66
67         if (S1 == 4)
68                 retVal[3] = T1(1);
69
70         for (int ndx = 0; ndx < de::min(S1, S2); ++ndx)
71                 retVal[ndx] = T1(v[ndx]);
72
73         return retVal;
74 }
75
76 class FloatLoader
77 {
78 public:
79         virtual                         ~FloatLoader    (void) {};
80
81         // returns the value loaded
82         virtual tcu::Vec4       load                    (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const = 0;
83 };
84
85 #define GEN_DIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES)                                \
86         class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader                                          \
87         {                                                                                                                                                                       \
88         public:                                                                                                                                                         \
89                 enum                                                                                                                                                    \
90                 {                                                                                                                                                               \
91                         NORMALIZING = 0,                                                                                                                        \
92                 };                                                                                                                                                              \
93                 enum                                                                                                                                                    \
94                 {                                                                                                                                                               \
95                         COMPONENTS = (COMPS)                                                                                                            \
96                 };                                                                                                                                                              \
97                 typedef TYPE Type;                                                                                                                              \
98                                                                                                                                                                                 \
99                 tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const   \
100                 {                                                                                                                                                               \
101                         tcu::Vector<TYPE, COMPONENTS> value;                                                                            \
102                         value = convertToTypeVec<Type, COMPONENTS>(v);                                                          \
103                                                                                                                                                                                 \
104                         gl.glVertexAttrib ##COMPS ##TYPECODE VALUES;                                                            \
105                         return convertToTypeVec<float, 4>(value);                                                                       \
106                 }                                                                                                                                                               \
107                                                                                                                                                                                 \
108                 static const char* getCaseName (void)                                                                                   \
109                 {                                                                                                                                                               \
110                         return CASENAME;                                                                                                                        \
111                 }                                                                                                                                                               \
112                                                                                                                                                                                 \
113                 static const char* getName (void)                                                                                               \
114                 {                                                                                                                                                               \
115                         return "VertexAttrib" #COMPS #TYPECODE;                                                                         \
116                 }                                                                                                                                                               \
117         }
118
119 #define GEN_INDIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME)                                              \
120         class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader                                          \
121         {                                                                                                                                                                       \
122         public:                                                                                                                                                         \
123                 enum                                                                                                                                                    \
124                 {                                                                                                                                                               \
125                         NORMALIZING = 0,                                                                                                                        \
126                 };                                                                                                                                                              \
127                 enum                                                                                                                                                    \
128                 {                                                                                                                                                               \
129                         COMPONENTS = (COMPS)                                                                                                            \
130                 };                                                                                                                                                              \
131                 typedef TYPE Type;                                                                                                                              \
132                                                                                                                                                                                 \
133                 tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const   \
134                 {                                                                                                                                                               \
135                         tcu::Vector<TYPE, COMPONENTS> value;                                                                            \
136                         value = convertToTypeVec<Type, COMPONENTS>(v);                                                          \
137                                                                                                                                                                                 \
138                         gl.glVertexAttrib ##COMPS ##TYPECODE (index, value.getPtr());                           \
139                         return convertToTypeVec<float, 4>(value);                                                                       \
140                 }                                                                                                                                                               \
141                                                                                                                                                                                 \
142                 static const char* getCaseName (void)                                                                                   \
143                 {                                                                                                                                                               \
144                         return CASENAME;                                                                                                                        \
145                 }                                                                                                                                                               \
146                                                                                                                                                                                 \
147                 static const char* getName (void)                                                                                               \
148                 {                                                                                                                                                               \
149                         return "VertexAttrib" #COMPS #TYPECODE;                                                                         \
150                 }                                                                                                                                                               \
151         }
152
153 GEN_DIRECT_FLOAT_LOADER(float, 1, f, "vertex_attrib_1f", (index, value.x()));
154 GEN_DIRECT_FLOAT_LOADER(float, 2, f, "vertex_attrib_2f", (index, value.x(), value.y()));
155 GEN_DIRECT_FLOAT_LOADER(float, 3, f, "vertex_attrib_3f", (index, value.x(), value.y(), value.z()));
156 GEN_DIRECT_FLOAT_LOADER(float, 4, f, "vertex_attrib_4f", (index, value.x(), value.y(), value.z(), value.w()));
157
158 GEN_INDIRECT_FLOAT_LOADER(float, 1, fv, "vertex_attrib_1fv");
159 GEN_INDIRECT_FLOAT_LOADER(float, 2, fv, "vertex_attrib_2fv");
160 GEN_INDIRECT_FLOAT_LOADER(float, 3, fv, "vertex_attrib_3fv");
161 GEN_INDIRECT_FLOAT_LOADER(float, 4, fv, "vertex_attrib_4fv");
162
163 class AttributeCase : public TestCase
164 {
165                                                                         AttributeCase                   (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType);
166 public:
167         template<typename LoaderType>
168         static AttributeCase*                   create                                  (Context& ctx, glu::DataType dataType);
169                                                                         ~AttributeCase                  (void);
170
171 private:
172         void                                                    init                                    (void);
173         void                                                    deinit                                  (void);
174         IterateResult                                   iterate                                 (void);
175
176         glu::DataType                                   getTargetType                   (void) const;
177         std::string                                             genVertexSource                 (void) const;
178         bool                                                    renderWithValue                 (const tcu::Vec4& v);
179         tcu::Vec4                                               computeColor                    (const tcu::Vec4& value);
180         bool                                                    verifyUnicoloredBuffer  (const tcu::Surface& scene, const tcu::Vec4& refValue);
181
182         const bool                                              m_normalizing;
183         const bool                                              m_useNegativeValues;
184         const char* const                               m_funcName;
185         const glu::DataType                             m_dataType;
186         const FloatLoader*                              m_loader;
187         glu::ShaderProgram*                             m_program;
188         deUint32                                                m_bufID;
189         bool                                                    m_allIterationsPassed;
190         int                                                             m_iteration;
191
192         enum
193         {
194                 RENDER_SIZE = 32
195         };
196 };
197
198 AttributeCase::AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType)
199         : TestCase                              (ctx, name, desc)
200         , m_normalizing                 (normalizing)
201         , m_useNegativeValues   (useNegative)
202         , m_funcName                    (funcName)
203         , m_dataType                    (dataType)
204         , m_loader                              (DE_NULL)
205         , m_program                             (DE_NULL)
206         , m_bufID                               (0)
207         , m_allIterationsPassed (true)
208         , m_iteration                   (0)
209 {
210 }
211
212 template<typename LoaderType>
213 AttributeCase* AttributeCase::create (Context& ctx, glu::DataType dataType)
214 {
215         AttributeCase* retVal = new AttributeCase(ctx,
216                                                                                           LoaderType::getCaseName(),
217                                                                                           (std::string("Test ") + LoaderType::getName()).c_str(),
218                                                                                           LoaderType::getName(),
219                                                                                           LoaderType::NORMALIZING != 0,
220                                                                                           std::numeric_limits<typename LoaderType::Type>::is_signed,
221                                                                                           dataType);
222         retVal->m_loader = new LoaderType();
223         return retVal;
224 }
225
226 AttributeCase::~AttributeCase (void)
227 {
228         deinit();
229 }
230
231 void AttributeCase::init (void)
232 {
233         if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE)
234                 throw tcu::NotSupportedError("Render target must be at least " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE));
235
236         // log test info
237
238         {
239                 const float                     maxRange                = (m_normalizing) ? (1.0f) : (s_valueRange);
240                 const float                     minRange                = (m_useNegativeValues) ? (-maxRange) : (0.0f);
241
242                 m_testCtx.getLog()
243                         << tcu::TestLog::Message
244                         << "Loading attribute values using " << m_funcName << "\n"
245                         << "Attribute type: " << glu::getDataTypeName(m_dataType) << "\n"
246                         << "Attribute value range: [" << minRange << ", " << maxRange << "]"
247                         << tcu::TestLog::EndMessage;
248         }
249
250         // gen shader and base quad
251
252         m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(s_passThroughFragmentShaderSource));
253         m_testCtx.getLog() << *m_program;
254         if (!m_program->isOk())
255                 throw tcu::TestError("could not build program");
256
257         {
258                 const tcu::Vec4 fullscreenQuad[] =
259                 {
260                         tcu::Vec4( 1.0f,  1.0f, 0.0f, 1.0f),
261                         tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
262                         tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f),
263                         tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
264                 };
265
266                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
267
268                 gl.genBuffers(1, &m_bufID);
269                 gl.bindBuffer(GL_ARRAY_BUFFER, m_bufID);
270                 gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW);
271                 GLU_EXPECT_NO_ERROR(gl.getError(), "fill buffer");
272         }
273 }
274
275 void AttributeCase::deinit (void)
276 {
277         delete m_loader;
278         m_loader = DE_NULL;
279
280         delete m_program;
281         m_program = DE_NULL;
282
283         if (m_bufID)
284         {
285                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufID);
286                 m_bufID = 0;
287         }
288 }
289
290 AttributeCase::IterateResult AttributeCase::iterate (void)
291 {
292         static const tcu::Vec4 testValues[] =
293         {
294                 tcu::Vec4(0.0f, 0.5f, 0.2f, 1.0f),
295                 tcu::Vec4(0.1f, 0.7f, 1.0f, 0.6f),
296                 tcu::Vec4(0.4f, 0.2f, 0.0f, 0.5f),
297                 tcu::Vec4(0.5f, 0.0f, 0.9f, 0.1f),
298                 tcu::Vec4(0.6f, 0.2f, 0.2f, 0.9f),
299                 tcu::Vec4(0.9f, 1.0f, 0.0f, 0.0f),
300                 tcu::Vec4(1.0f, 0.5f, 0.3f, 0.8f),
301         };
302
303         const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", "Iteration " + de::toString(m_iteration+1) + "/" + de::toString(DE_LENGTH_OF_ARRAY(testValues)));
304
305         // Test normalizing transfers with whole range, non-normalizing with up to s_valueRange
306         const tcu::Vec4 testValue = ((m_useNegativeValues) ? (testValues[m_iteration] * 2.0f - tcu::Vec4(1.0f)) : (testValues[m_iteration])) * ((m_normalizing) ? (1.0f) : ((float)s_valueRange));
307
308         if (!renderWithValue(testValue))
309                 m_allIterationsPassed = false;
310
311         // continue
312
313         if (++m_iteration < DE_LENGTH_OF_ARRAY(testValues))
314                 return CONTINUE;
315
316         if (m_allIterationsPassed)
317                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
318         else
319                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected values");
320
321         return STOP;
322 }
323
324 std::string AttributeCase::genVertexSource (void) const
325 {
326         const int                       vectorSize      = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeScalarSize(m_dataType)) : (-1);
327         const char* const       vectorType      = glu::getDataTypeName((glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) : (glu::TYPE_FLOAT));
328         const int                       components      = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType));
329         std::ostringstream      buf;
330
331         buf <<  "attribute highp vec4 a_position;\n"
332                         "attribute highp " << glu::getDataTypeName(m_dataType) << " a_value;\n"
333                         "varying highp vec4 v_color;\n"
334                         "void main (void)\n"
335                         "{\n"
336                         "       gl_Position = a_position;\n"
337                         "\n";
338
339         if (m_normalizing)
340                 buf << "        highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ");\n";
341         else
342                 buf << "        highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ") / float(" << s_valueRange << ");\n";
343
344         if (m_useNegativeValues)
345                 buf << "        highp " << vectorType << " positiveNormalizedValue = (normalizedValue + " << vectorType << "(1.0)) / 2.0;\n";
346         else
347                 buf << "        highp " << vectorType << " positiveNormalizedValue = normalizedValue;\n";
348
349         if (components == 1)
350                 buf << "        v_color = vec4(positiveNormalizedValue, 0.0, 0.0, 1.0);\n";
351         else if (components == 2)
352                 buf << "        v_color = vec4(positiveNormalizedValue.xy, 0.0, 1.0);\n";
353         else if (components == 3)
354                 buf << "        v_color = vec4(positiveNormalizedValue.xyz, 1.0);\n";
355         else if (components == 4)
356                 buf << "        v_color = vec4((positiveNormalizedValue.xy + positiveNormalizedValue.zz) / 2.0, positiveNormalizedValue.w, 1.0);\n";
357         else
358                 DE_ASSERT(DE_FALSE);
359
360         buf << "}\n";
361
362         return buf.str();
363 }
364
365 bool AttributeCase::renderWithValue (const tcu::Vec4& v)
366 {
367         glu::CallLogWrapper     gl                              (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
368
369         gl.enableLogging(true);
370
371         const int                       positionIndex   = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
372         const int                       valueIndex              = gl.glGetAttribLocation(m_program->getProgram(), "a_value");
373         tcu::Surface            dest                    (RENDER_SIZE, RENDER_SIZE);
374         tcu::Vec4                       loadedValue;
375
376         gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
377         gl.glClear(GL_COLOR_BUFFER_BIT);
378         gl.glViewport(0, 0, RENDER_SIZE, RENDER_SIZE);
379         GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
380
381         gl.glBindBuffer(GL_ARRAY_BUFFER, m_bufID);
382         gl.glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
383         gl.glEnableVertexAttribArray(positionIndex);
384         GLU_EXPECT_NO_ERROR(gl.glGetError(), "position va");
385
386         // transfer test value. Load to the second column in the matrix case
387         loadedValue = m_loader->load(gl, (glu::isDataTypeMatrix(m_dataType)) ? (valueIndex + 1) : (valueIndex), v);
388         GLU_EXPECT_NO_ERROR(gl.glGetError(), "default va");
389
390         gl.glUseProgram(m_program->getProgram());
391         gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
392         gl.glUseProgram(0);
393         GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
394
395         glu::readPixels(m_context.getRenderContext(), 0, 0, dest.getAccess());
396
397         // check whole result is colored correctly
398         return verifyUnicoloredBuffer(dest, computeColor(loadedValue));
399 }
400
401 tcu::Vec4 AttributeCase::computeColor (const tcu::Vec4& value)
402 {
403         const tcu::Vec4 normalizedValue                 = value / ((m_normalizing) ? (1.0f) : ((float)s_valueRange));
404         const tcu::Vec4 positiveNormalizedValue = ((m_useNegativeValues) ? ((normalizedValue + tcu::Vec4(1.0f)) / 2.0f) : (normalizedValue));
405         const int               components                              = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType));
406
407         if (components == 1)
408                 return tcu::Vec4(positiveNormalizedValue.x(), 0.0f, 0.0f, 1.0f);
409         else if (components == 2)
410                 return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), 0.0f, 1.0f);
411         else if (components == 3)
412                 return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), positiveNormalizedValue.z(), 1.0f);
413         else if (components == 4)
414                 return tcu::Vec4((positiveNormalizedValue.x() + positiveNormalizedValue.z()) / 2.0f, (positiveNormalizedValue.y() + positiveNormalizedValue.z()) / 2.0f, positiveNormalizedValue.w(), 1.0f);
415         else
416                 DE_ASSERT(DE_FALSE);
417
418         return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
419 }
420
421 bool AttributeCase::verifyUnicoloredBuffer (const tcu::Surface& scene, const tcu::Vec4& refValue)
422 {
423         tcu::Surface    errorMask               (RENDER_SIZE, RENDER_SIZE);
424         const tcu::RGBA refColor                (refValue);
425         const int               resultThreshold = 2;
426         const tcu::RGBA colorThreshold  = m_context.getRenderTarget().getPixelFormat().getColorThreshold() * resultThreshold;
427         bool                    error                   = false;
428
429         tcu::RGBA               exampleColor;
430         tcu::IVec2              examplePos;
431
432         tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
433
434         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying rendered image. Expecting color " << refColor << ", threshold " << colorThreshold << tcu::TestLog::EndMessage;
435
436         for (int y = 0; y < RENDER_SIZE; ++y)
437         for (int x = 0; x < RENDER_SIZE; ++x)
438         {
439                 const tcu::RGBA color = scene.getPixel(x, y);
440
441                 if (de::abs(color.getRed()   - refColor.getRed())   > colorThreshold.getRed()   ||
442                         de::abs(color.getGreen() - refColor.getGreen()) > colorThreshold.getGreen() ||
443                         de::abs(color.getBlue()  - refColor.getBlue())  > colorThreshold.getBlue())
444                 {
445                         // first error
446                         if (!error)
447                         {
448                                 exampleColor = color;
449                                 examplePos = tcu::IVec2(x, y);
450                         }
451
452                         error = true;
453                         errorMask.setPixel(x, y, tcu::RGBA::red());
454                 }
455         }
456
457         if (!error)
458                 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered image is valid." << tcu::TestLog::EndMessage;
459         else
460         {
461                 m_testCtx.getLog()      << tcu::TestLog::Message
462                                                         << "Found invalid pixel(s).\n"
463                                                         << "Pixel at (" << examplePos.x() << ", " << examplePos.y() << ") color: " << exampleColor
464                                                         << tcu::TestLog::EndMessage
465                                                         << tcu::TestLog::ImageSet("Result", "Render result")
466                                                         << tcu::TestLog::Image("Result", "Result", scene)
467                                                         << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask)
468                                                         << tcu::TestLog::EndImageSet;
469         }
470
471         return !error;
472 }
473
474 } // anonymous
475
476 DefaultVertexAttributeTests::DefaultVertexAttributeTests (Context& context)
477         : TestCaseGroup(context, "default_vertex_attrib", "Test default vertex attributes")
478 {
479 }
480
481 DefaultVertexAttributeTests::~DefaultVertexAttributeTests (void)
482 {
483 }
484
485 void DefaultVertexAttributeTests::init (void)
486 {
487         struct Target
488         {
489                 const char*             name;
490                 glu::DataType   dataType;
491                 bool                    reducedTestSets;        // !< use reduced coverage
492         };
493
494         static const Target floatTargets[] =
495         {
496                 { "float",      glu::TYPE_FLOAT,                false   },
497                 { "vec2",       glu::TYPE_FLOAT_VEC2,   true    },
498                 { "vec3",       glu::TYPE_FLOAT_VEC3,   true    },
499                 { "vec4",       glu::TYPE_FLOAT_VEC4,   false   },
500                 { "mat2",       glu::TYPE_FLOAT_MAT2,   true    },
501                 { "mat3",       glu::TYPE_FLOAT_MAT3,   true    },
502                 { "mat4",       glu::TYPE_FLOAT_MAT4,   false   },
503         };
504
505         // float targets
506
507         for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(floatTargets); ++targetNdx)
508         {
509                 tcu::TestCaseGroup* const       group   = new tcu::TestCaseGroup(m_testCtx, floatTargets[targetNdx].name, (std::string("test with ") + floatTargets[targetNdx].name).c_str());
510                 const bool                                      fullSet = !floatTargets[targetNdx].reducedTestSets;
511
512 #define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, floatTargets[targetNdx].dataType))
513 #define ADD_REDUCED_CASE(X)     if (fullSet) ADD_CASE(X)
514
515                 ADD_CASE                (LoaderVertexAttrib1f);
516                 ADD_REDUCED_CASE(LoaderVertexAttrib2f);
517                 ADD_REDUCED_CASE(LoaderVertexAttrib3f);
518                 ADD_CASE                (LoaderVertexAttrib4f);
519
520                 ADD_CASE                (LoaderVertexAttrib1fv);
521                 ADD_REDUCED_CASE(LoaderVertexAttrib2fv);
522                 ADD_REDUCED_CASE(LoaderVertexAttrib3fv);
523                 ADD_CASE                (LoaderVertexAttrib4fv);
524
525 #undef ADD_CASE
526 #undef ADD_REDUCED_CASE
527
528                 addChild(group);
529         }
530 }
531
532 } // Functional
533 } // gles2
534 } // deqp