xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fDefaultVertexAttributeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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>
convertToTypeVec(const tcu::Vector<T2,S2> & v)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:
~FloatLoader(void)79     virtual ~FloatLoader(void)
80     {
81     }
82 
83     // returns the value loaded
84     virtual tcu::Vec4 load(glu::CallLogWrapper &gl, int index, const tcu::Vec4 &v) const = 0;
85 };
86 
87 #define GEN_DIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES)             \
88     class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader                   \
89     {                                                                                \
90     public:                                                                          \
91         enum                                                                         \
92         {                                                                            \
93             NORMALIZING = 0,                                                         \
94         };                                                                           \
95         enum                                                                         \
96         {                                                                            \
97             COMPONENTS = (COMPS)                                                     \
98         };                                                                           \
99         typedef TYPE Type;                                                           \
100                                                                                      \
101         tcu::Vec4 load(glu::CallLogWrapper &gl, int index, const tcu::Vec4 &v) const \
102         {                                                                            \
103             tcu::Vector<TYPE, COMPONENTS> value;                                     \
104             value = convertToTypeVec<Type, COMPONENTS>(v);                           \
105                                                                                      \
106             gl.glVertexAttrib##COMPS##TYPECODE VALUES;                               \
107             return convertToTypeVec<float, 4>(value);                                \
108         }                                                                            \
109                                                                                      \
110         static const char *getCaseName(void)                                         \
111         {                                                                            \
112             return CASENAME;                                                         \
113         }                                                                            \
114                                                                                      \
115         static const char *getName(void)                                             \
116         {                                                                            \
117             return "VertexAttrib" #COMPS #TYPECODE;                                  \
118         }                                                                            \
119     }
120 
121 #define GEN_INDIRECT_FLOAT_LOADER(TYPE, COMPS, TYPECODE, CASENAME)                   \
122     class LoaderVertexAttrib##COMPS##TYPECODE : public FloatLoader                   \
123     {                                                                                \
124     public:                                                                          \
125         enum                                                                         \
126         {                                                                            \
127             NORMALIZING = 0,                                                         \
128         };                                                                           \
129         enum                                                                         \
130         {                                                                            \
131             COMPONENTS = (COMPS)                                                     \
132         };                                                                           \
133         typedef TYPE Type;                                                           \
134                                                                                      \
135         tcu::Vec4 load(glu::CallLogWrapper &gl, int index, const tcu::Vec4 &v) const \
136         {                                                                            \
137             tcu::Vector<TYPE, COMPONENTS> value;                                     \
138             value = convertToTypeVec<Type, COMPONENTS>(v);                           \
139                                                                                      \
140             gl.glVertexAttrib##COMPS##TYPECODE(index, value.getPtr());               \
141             return convertToTypeVec<float, 4>(value);                                \
142         }                                                                            \
143                                                                                      \
144         static const char *getCaseName(void)                                         \
145         {                                                                            \
146             return CASENAME;                                                         \
147         }                                                                            \
148                                                                                      \
149         static const char *getName(void)                                             \
150         {                                                                            \
151             return "VertexAttrib" #COMPS #TYPECODE;                                  \
152         }                                                                            \
153     }
154 
155 GEN_DIRECT_FLOAT_LOADER(float, 1, f, "vertex_attrib_1f", (index, value.x()));
156 GEN_DIRECT_FLOAT_LOADER(float, 2, f, "vertex_attrib_2f", (index, value.x(), value.y()));
157 GEN_DIRECT_FLOAT_LOADER(float, 3, f, "vertex_attrib_3f", (index, value.x(), value.y(), value.z()));
158 GEN_DIRECT_FLOAT_LOADER(float, 4, f, "vertex_attrib_4f", (index, value.x(), value.y(), value.z(), value.w()));
159 
160 GEN_INDIRECT_FLOAT_LOADER(float, 1, fv, "vertex_attrib_1fv");
161 GEN_INDIRECT_FLOAT_LOADER(float, 2, fv, "vertex_attrib_2fv");
162 GEN_INDIRECT_FLOAT_LOADER(float, 3, fv, "vertex_attrib_3fv");
163 GEN_INDIRECT_FLOAT_LOADER(float, 4, fv, "vertex_attrib_4fv");
164 
165 class AttributeCase : public TestCase
166 {
167     AttributeCase(Context &ctx, const char *name, const char *desc, const char *funcName, bool normalizing,
168                   bool useNegative, glu::DataType dataType);
169 
170 public:
171     template <typename LoaderType>
172     static AttributeCase *create(Context &ctx, glu::DataType dataType);
173     ~AttributeCase(void);
174 
175 private:
176     void init(void);
177     void deinit(void);
178     IterateResult iterate(void);
179 
180     glu::DataType getTargetType(void) const;
181     std::string genVertexSource(void) const;
182     bool renderWithValue(const tcu::Vec4 &v);
183     tcu::Vec4 computeColor(const tcu::Vec4 &value);
184     bool verifyUnicoloredBuffer(const tcu::Surface &scene, const tcu::Vec4 &refValue);
185 
186     const bool m_normalizing;
187     const bool m_useNegativeValues;
188     const char *const m_funcName;
189     const glu::DataType m_dataType;
190     const FloatLoader *m_loader;
191     glu::ShaderProgram *m_program;
192     uint32_t m_bufID;
193     bool m_allIterationsPassed;
194     int m_iteration;
195 
196     enum
197     {
198         RENDER_SIZE = 32
199     };
200 };
201 
AttributeCase(Context & ctx,const char * name,const char * desc,const char * funcName,bool normalizing,bool useNegative,glu::DataType dataType)202 AttributeCase::AttributeCase(Context &ctx, const char *name, const char *desc, const char *funcName, bool normalizing,
203                              bool useNegative, glu::DataType dataType)
204     : TestCase(ctx, name, desc)
205     , m_normalizing(normalizing)
206     , m_useNegativeValues(useNegative)
207     , m_funcName(funcName)
208     , m_dataType(dataType)
209     , m_loader(DE_NULL)
210     , m_program(DE_NULL)
211     , m_bufID(0)
212     , m_allIterationsPassed(true)
213     , m_iteration(0)
214 {
215 }
216 
217 template <typename LoaderType>
create(Context & ctx,glu::DataType dataType)218 AttributeCase *AttributeCase::create(Context &ctx, glu::DataType dataType)
219 {
220     AttributeCase *retVal = new AttributeCase(
221         ctx, LoaderType::getCaseName(), (std::string("Test ") + LoaderType::getName()).c_str(), LoaderType::getName(),
222         LoaderType::NORMALIZING != 0, std::numeric_limits<typename LoaderType::Type>::is_signed, dataType);
223     retVal->m_loader = new LoaderType();
224     return retVal;
225 }
226 
~AttributeCase(void)227 AttributeCase::~AttributeCase(void)
228 {
229     deinit();
230 }
231 
init(void)232 void AttributeCase::init(void)
233 {
234     if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE)
235         throw tcu::NotSupportedError("Render target must be at least " + de::toString<int>(RENDER_SIZE) + "x" +
236                                      de::toString<int>(RENDER_SIZE));
237 
238     // log test info
239 
240     {
241         const float maxRange = (m_normalizing) ? (1.0f) : (s_valueRange);
242         const float minRange = (m_useNegativeValues) ? (-maxRange) : (0.0f);
243 
244         m_testCtx.getLog() << tcu::TestLog::Message << "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(),
253                                        glu::ProgramSources() << glu::VertexSource(genVertexSource())
254                                                              << glu::FragmentSource(s_passThroughFragmentShaderSource));
255     m_testCtx.getLog() << *m_program;
256     if (!m_program->isOk())
257         throw tcu::TestError("could not build program");
258 
259     {
260         const tcu::Vec4 fullscreenQuad[] = {
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             tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
265         };
266 
267         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
268 
269         gl.genBuffers(1, &m_bufID);
270         gl.bindBuffer(GL_ARRAY_BUFFER, m_bufID);
271         gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW);
272         GLU_EXPECT_NO_ERROR(gl.getError(), "fill buffer");
273     }
274 }
275 
deinit(void)276 void AttributeCase::deinit(void)
277 {
278     delete m_loader;
279     m_loader = DE_NULL;
280 
281     delete m_program;
282     m_program = DE_NULL;
283 
284     if (m_bufID)
285     {
286         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufID);
287         m_bufID = 0;
288     }
289 }
290 
iterate(void)291 AttributeCase::IterateResult AttributeCase::iterate(void)
292 {
293     static const tcu::Vec4 testValues[] = {
294         tcu::Vec4(0.0f, 0.5f, 0.2f, 1.0f), tcu::Vec4(0.1f, 0.7f, 1.0f, 0.6f), tcu::Vec4(0.4f, 0.2f, 0.0f, 0.5f),
295         tcu::Vec4(0.5f, 0.0f, 0.9f, 0.1f), tcu::Vec4(0.6f, 0.2f, 0.2f, 0.9f), tcu::Vec4(0.9f, 1.0f, 0.0f, 0.0f),
296         tcu::Vec4(1.0f, 0.5f, 0.3f, 0.8f),
297     };
298 
299     const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration",
300                                         "Iteration " + de::toString(m_iteration + 1) + "/" +
301                                             de::toString(DE_LENGTH_OF_ARRAY(testValues)));
302 
303     // Test normalizing transfers with whole range, non-normalizing with up to s_valueRange
304     const tcu::Vec4 testValue =
305         ((m_useNegativeValues) ? (testValues[m_iteration] * 2.0f - tcu::Vec4(1.0f)) : (testValues[m_iteration])) *
306         ((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 
genVertexSource(void) const324 std::string AttributeCase::genVertexSource(void) const
325 {
326     const int vectorSize         = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) :
327                                    (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeScalarSize(m_dataType)) :
328                                                                          (-1);
329     const char *const vectorType = glu::getDataTypeName(
330         (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) :
331         (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeVector(glu::TYPE_FLOAT, vectorSize)) :
332                                               (glu::TYPE_FLOAT));
333     const int components = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) :
334                                                                  (glu::getDataTypeScalarSize(m_dataType));
335     std::ostringstream buf;
336 
337     buf << "attribute highp vec4 a_position;\n"
338            "attribute highp "
339         << glu::getDataTypeName(m_dataType)
340         << " a_value;\n"
341            "varying highp vec4 v_color;\n"
342            "void main (void)\n"
343            "{\n"
344            "    gl_Position = a_position;\n"
345            "\n";
346 
347     if (m_normalizing)
348         buf << "    highp " << vectorType << " normalizedValue = "
349             << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value"
350             << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ");\n";
351     else
352         buf << "    highp " << vectorType << " normalizedValue = "
353             << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value"
354             << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ") / float(" << s_valueRange << ");\n";
355 
356     if (m_useNegativeValues)
357         buf << "    highp " << vectorType << " positiveNormalizedValue = (normalizedValue + " << vectorType
358             << "(1.0)) / 2.0;\n";
359     else
360         buf << "    highp " << vectorType << " positiveNormalizedValue = normalizedValue;\n";
361 
362     if (components == 1)
363         buf << "    v_color = vec4(positiveNormalizedValue, 0.0, 0.0, 1.0);\n";
364     else if (components == 2)
365         buf << "    v_color = vec4(positiveNormalizedValue.xy, 0.0, 1.0);\n";
366     else if (components == 3)
367         buf << "    v_color = vec4(positiveNormalizedValue.xyz, 1.0);\n";
368     else if (components == 4)
369         buf << "    v_color = vec4((positiveNormalizedValue.xy + positiveNormalizedValue.zz) / 2.0, "
370                "positiveNormalizedValue.w, 1.0);\n";
371     else
372         DE_ASSERT(false);
373 
374     buf << "}\n";
375 
376     return buf.str();
377 }
378 
renderWithValue(const tcu::Vec4 & v)379 bool AttributeCase::renderWithValue(const tcu::Vec4 &v)
380 {
381     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
382 
383     gl.enableLogging(true);
384 
385     const int positionIndex = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
386     const int valueIndex    = gl.glGetAttribLocation(m_program->getProgram(), "a_value");
387     tcu::Surface dest(RENDER_SIZE, RENDER_SIZE);
388     tcu::Vec4 loadedValue;
389 
390     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
391     gl.glClear(GL_COLOR_BUFFER_BIT);
392     gl.glViewport(0, 0, RENDER_SIZE, RENDER_SIZE);
393     GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
394 
395     gl.glBindBuffer(GL_ARRAY_BUFFER, m_bufID);
396     gl.glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
397     gl.glEnableVertexAttribArray(positionIndex);
398     GLU_EXPECT_NO_ERROR(gl.glGetError(), "position va");
399 
400     // transfer test value. Load to the second column in the matrix case
401     loadedValue = m_loader->load(gl, (glu::isDataTypeMatrix(m_dataType)) ? (valueIndex + 1) : (valueIndex), v);
402     GLU_EXPECT_NO_ERROR(gl.glGetError(), "default va");
403 
404     gl.glUseProgram(m_program->getProgram());
405     gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
406     gl.glUseProgram(0);
407     GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
408 
409     glu::readPixels(m_context.getRenderContext(), 0, 0, dest.getAccess());
410 
411     // check whole result is colored correctly
412     return verifyUnicoloredBuffer(dest, computeColor(loadedValue));
413 }
414 
computeColor(const tcu::Vec4 & value)415 tcu::Vec4 AttributeCase::computeColor(const tcu::Vec4 &value)
416 {
417     const tcu::Vec4 normalizedValue = value / ((m_normalizing) ? (1.0f) : ((float)s_valueRange));
418     const tcu::Vec4 positiveNormalizedValue =
419         ((m_useNegativeValues) ? ((normalizedValue + tcu::Vec4(1.0f)) / 2.0f) : (normalizedValue));
420     const int components = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) :
421                                                                  (glu::getDataTypeScalarSize(m_dataType));
422 
423     if (components == 1)
424         return tcu::Vec4(positiveNormalizedValue.x(), 0.0f, 0.0f, 1.0f);
425     else if (components == 2)
426         return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), 0.0f, 1.0f);
427     else if (components == 3)
428         return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), positiveNormalizedValue.z(), 1.0f);
429     else if (components == 4)
430         return tcu::Vec4((positiveNormalizedValue.x() + positiveNormalizedValue.z()) / 2.0f,
431                          (positiveNormalizedValue.y() + positiveNormalizedValue.z()) / 2.0f,
432                          positiveNormalizedValue.w(), 1.0f);
433     else
434         DE_ASSERT(false);
435 
436     return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
437 }
438 
verifyUnicoloredBuffer(const tcu::Surface & scene,const tcu::Vec4 & refValue)439 bool AttributeCase::verifyUnicoloredBuffer(const tcu::Surface &scene, const tcu::Vec4 &refValue)
440 {
441     tcu::Surface errorMask(RENDER_SIZE, RENDER_SIZE);
442     const tcu::RGBA refColor(refValue);
443     const int resultThreshold      = 2;
444     const tcu::RGBA colorThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold() * resultThreshold;
445     bool error                     = false;
446 
447     tcu::RGBA exampleColor;
448     tcu::IVec2 examplePos;
449 
450     tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
451 
452     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying rendered image. Expecting color " << refColor
453                        << ", threshold " << colorThreshold << tcu::TestLog::EndMessage;
454 
455     for (int y = 0; y < RENDER_SIZE; ++y)
456         for (int x = 0; x < RENDER_SIZE; ++x)
457         {
458             const tcu::RGBA color = scene.getPixel(x, y);
459 
460             if (de::abs(color.getRed() - refColor.getRed()) > colorThreshold.getRed() ||
461                 de::abs(color.getGreen() - refColor.getGreen()) > colorThreshold.getGreen() ||
462                 de::abs(color.getBlue() - refColor.getBlue()) > colorThreshold.getBlue())
463             {
464                 // first error
465                 if (!error)
466                 {
467                     exampleColor = color;
468                     examplePos   = tcu::IVec2(x, y);
469                 }
470 
471                 error = true;
472                 errorMask.setPixel(x, y, tcu::RGBA::red());
473             }
474         }
475 
476     if (!error)
477         m_testCtx.getLog() << tcu::TestLog::Message << "Rendered image is valid." << tcu::TestLog::EndMessage;
478     else
479     {
480         m_testCtx.getLog() << tcu::TestLog::Message << "Found invalid pixel(s).\n"
481                            << "Pixel at (" << examplePos.x() << ", " << examplePos.y() << ") color: " << exampleColor
482                            << tcu::TestLog::EndMessage << tcu::TestLog::ImageSet("Result", "Render result")
483                            << tcu::TestLog::Image("Result", "Result", scene)
484                            << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask) << tcu::TestLog::EndImageSet;
485     }
486 
487     return !error;
488 }
489 
490 } // namespace
491 
DefaultVertexAttributeTests(Context & context)492 DefaultVertexAttributeTests::DefaultVertexAttributeTests(Context &context)
493     : TestCaseGroup(context, "default_vertex_attrib", "Test default vertex attributes")
494 {
495 }
496 
~DefaultVertexAttributeTests(void)497 DefaultVertexAttributeTests::~DefaultVertexAttributeTests(void)
498 {
499 }
500 
init(void)501 void DefaultVertexAttributeTests::init(void)
502 {
503     struct Target
504     {
505         const char *name;
506         glu::DataType dataType;
507         bool reducedTestSets; // !< use reduced coverage
508     };
509 
510     static const Target floatTargets[] = {
511         {"float", glu::TYPE_FLOAT, false},     {"vec2", glu::TYPE_FLOAT_VEC2, true},
512         {"vec3", glu::TYPE_FLOAT_VEC3, true},  {"vec4", glu::TYPE_FLOAT_VEC4, false},
513         {"mat2", glu::TYPE_FLOAT_MAT2, true},  {"mat3", glu::TYPE_FLOAT_MAT3, true},
514         {"mat4", glu::TYPE_FLOAT_MAT4, false},
515     };
516 
517     // float targets
518 
519     for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(floatTargets); ++targetNdx)
520     {
521         tcu::TestCaseGroup *const group =
522             new tcu::TestCaseGroup(m_testCtx, floatTargets[targetNdx].name,
523                                    (std::string("test with ") + floatTargets[targetNdx].name).c_str());
524         const bool fullSet = !floatTargets[targetNdx].reducedTestSets;
525 
526 #define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, floatTargets[targetNdx].dataType))
527 #define ADD_REDUCED_CASE(X) \
528     if (fullSet)            \
529     ADD_CASE(X)
530 
531         ADD_CASE(LoaderVertexAttrib1f);
532         ADD_REDUCED_CASE(LoaderVertexAttrib2f);
533         ADD_REDUCED_CASE(LoaderVertexAttrib3f);
534         ADD_CASE(LoaderVertexAttrib4f);
535 
536         ADD_CASE(LoaderVertexAttrib1fv);
537         ADD_REDUCED_CASE(LoaderVertexAttrib2fv);
538         ADD_REDUCED_CASE(LoaderVertexAttrib3fv);
539         ADD_CASE(LoaderVertexAttrib4fv);
540 
541 #undef ADD_CASE
542 #undef ADD_REDUCED_CASE
543 
544         addChild(group);
545     }
546 }
547 
548 } // namespace Functional
549 } // namespace gles2
550 } // namespace deqp
551