1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 "es3fDefaultVertexAttributeTests.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 gles3
45 {
46 namespace Functional
47 {
48 namespace
49 {
50
51 static const int s_valueRange = 10;
52
53 static const char* const s_passThroughFragmentShaderSource = "#version 300 es\n"
54 "layout(location = 0) out mediump vec4 fragColor;\n"
55 "in mediump vec4 v_color;\n"
56 "void main (void)\n"
57 "{\n"
58 " fragColor = v_color;\n"
59 "}\n";
60
61 template <typename T1, int S1, typename T2, int S2>
convertToTypeVec(const tcu::Vector<T2,S2> & v)62 tcu::Vector<T1, S1> convertToTypeVec (const tcu::Vector<T2, S2>& v)
63 {
64 tcu::Vector<T1, S1> retVal;
65
66 for (int ndx = 0; ndx < S1; ++ndx)
67 retVal[ndx] = T1(0);
68
69 if (S1 == 4)
70 retVal[3] = T1(1);
71
72 for (int ndx = 0; ndx < de::min(S1, S2); ++ndx)
73 retVal[ndx] = T1(v[ndx]);
74
75 return retVal;
76 }
77
78 class FloatLoader
79 {
80 public:
~FloatLoader(void)81 virtual ~FloatLoader (void) {};
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 #define GEN_DIRECT_INTEGER_LOADER(TYPE, COMPS, TYPECODE, CASENAME, VALUES) \
156 class LoaderVertexAttribI##COMPS##TYPECODE : public FloatLoader \
157 { \
158 public: \
159 enum \
160 { \
161 NORMALIZING = 0, \
162 }; \
163 enum \
164 { \
165 COMPONENTS = COMPS \
166 }; \
167 typedef TYPE Type; \
168 \
169 tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const \
170 { \
171 tcu::Vector<TYPE, COMPONENTS> value; \
172 value = convertToTypeVec<Type, COMPONENTS>(v); \
173 \
174 gl.glVertexAttribI ##COMPS ##TYPECODE VALUES; \
175 return convertToTypeVec<float, 4>(value); \
176 } \
177 \
178 static const char* getCaseName (void) \
179 { \
180 return CASENAME; \
181 } \
182 \
183 static const char* getName (void) \
184 { \
185 return "VertexAttrib" #COMPS #TYPECODE; \
186 } \
187 }
188
189 #define GEN_INDIRECT_INTEGER_LOADER(TYPE, COMPS, TYPECODE, CASENAME) \
190 class LoaderVertexAttribI##COMPS##TYPECODE : public FloatLoader \
191 { \
192 public: \
193 enum \
194 { \
195 NORMALIZING = 0, \
196 }; \
197 enum \
198 { \
199 COMPONENTS = COMPS \
200 }; \
201 typedef TYPE Type; \
202 \
203 tcu::Vec4 load (glu::CallLogWrapper& gl, int index, const tcu::Vec4& v) const \
204 { \
205 tcu::Vector<TYPE, COMPONENTS> value; \
206 value = convertToTypeVec<Type, COMPONENTS>(v); \
207 \
208 gl.glVertexAttribI ##COMPS ##TYPECODE (index, value.getPtr()); \
209 return convertToTypeVec<float, 4>(value); \
210 } \
211 \
212 static const char* getCaseName (void) \
213 { \
214 return CASENAME; \
215 } \
216 \
217 static const char* getName (void) \
218 { \
219 return "VertexAttrib" #COMPS #TYPECODE; \
220 } \
221 }
222
223 GEN_DIRECT_FLOAT_LOADER(float, 1, f, "vertex_attrib_1f", (index, value.x()));
224 GEN_DIRECT_FLOAT_LOADER(float, 2, f, "vertex_attrib_2f", (index, value.x(), value.y()));
225 GEN_DIRECT_FLOAT_LOADER(float, 3, f, "vertex_attrib_3f", (index, value.x(), value.y(), value.z()));
226 GEN_DIRECT_FLOAT_LOADER(float, 4, f, "vertex_attrib_4f", (index, value.x(), value.y(), value.z(), value.w()));
227
228 GEN_INDIRECT_FLOAT_LOADER(float, 1, fv, "vertex_attrib_1fv");
229 GEN_INDIRECT_FLOAT_LOADER(float, 2, fv, "vertex_attrib_2fv");
230 GEN_INDIRECT_FLOAT_LOADER(float, 3, fv, "vertex_attrib_3fv");
231 GEN_INDIRECT_FLOAT_LOADER(float, 4, fv, "vertex_attrib_4fv");
232
233 GEN_DIRECT_INTEGER_LOADER(deInt32, 4, i, "vertex_attribi_4i", (index, value.x(), value.y(), value.z(), value.w()));
234 GEN_INDIRECT_INTEGER_LOADER(deInt32, 4, iv, "vertex_attribi_4iv");
235
236 GEN_DIRECT_INTEGER_LOADER(deUint32, 4, ui, "vertex_attribi_4ui", (index, value.x(), value.y(), value.z(), value.w()));
237 GEN_INDIRECT_INTEGER_LOADER(deUint32, 4, uiv, "vertex_attribi_4uiv");
238
239 class AttributeCase : public TestCase
240 {
241 AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType);
242 public:
243 template<typename LoaderType>
244 static AttributeCase* create (Context& ctx, glu::DataType dataType);
245 ~AttributeCase (void);
246
247 private:
248 void init (void);
249 void deinit (void);
250 IterateResult iterate (void);
251
252 glu::DataType getTargetType (void) const;
253 std::string genVertexSource (void) const;
254 bool renderWithValue (const tcu::Vec4& v);
255 tcu::Vec4 computeColor (const tcu::Vec4& value);
256 bool verifyUnicoloredBuffer (const tcu::Surface& scene, const tcu::Vec4& refValue);
257
258 const bool m_normalizing;
259 const bool m_useNegativeValues;
260 const char* const m_funcName;
261 const glu::DataType m_dataType;
262 const FloatLoader* m_loader;
263 glu::ShaderProgram* m_program;
264 deUint32 m_bufID;
265 bool m_allIterationsPassed;
266 int m_iteration;
267
268 enum
269 {
270 RENDER_SIZE = 32
271 };
272 };
273
AttributeCase(Context & ctx,const char * name,const char * desc,const char * funcName,bool normalizing,bool useNegative,glu::DataType dataType)274 AttributeCase::AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType)
275 : TestCase (ctx, name, desc)
276 , m_normalizing (normalizing)
277 , m_useNegativeValues (useNegative)
278 , m_funcName (funcName)
279 , m_dataType (dataType)
280 , m_loader (DE_NULL)
281 , m_program (DE_NULL)
282 , m_bufID (0)
283 , m_allIterationsPassed (true)
284 , m_iteration (0)
285 {
286 }
287
288 template<typename LoaderType>
create(Context & ctx,glu::DataType dataType)289 AttributeCase* AttributeCase::create (Context& ctx, glu::DataType dataType)
290 {
291 AttributeCase* retVal = new AttributeCase(ctx,
292 LoaderType::getCaseName(),
293 (std::string("Test ") + LoaderType::getName()).c_str(),
294 LoaderType::getName(),
295 LoaderType::NORMALIZING != 0,
296 std::numeric_limits<typename LoaderType::Type>::is_signed,
297 dataType);
298 retVal->m_loader = new LoaderType();
299 return retVal;
300 }
301
~AttributeCase(void)302 AttributeCase::~AttributeCase (void)
303 {
304 deinit();
305 }
306
init(void)307 void AttributeCase::init (void)
308 {
309 if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE)
310 throw tcu::NotSupportedError("Render target must be at least " + de::toString<int>(RENDER_SIZE) + "x" + de::toString<int>(RENDER_SIZE));
311
312 // log test info
313
314 {
315 const float maxRange = (m_normalizing) ? (1.0f) : (s_valueRange);
316 const float minRange = (m_useNegativeValues) ? (-maxRange) : (0.0f);
317
318 m_testCtx.getLog()
319 << tcu::TestLog::Message
320 << "Loading attribute values using " << m_funcName << "\n"
321 << "Attribute type: " << glu::getDataTypeName(m_dataType) << "\n"
322 << "Attribute value range: [" << minRange << ", " << maxRange << "]"
323 << tcu::TestLog::EndMessage;
324 }
325
326 // gen shader and base quad
327
328 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(genVertexSource()) << glu::FragmentSource(s_passThroughFragmentShaderSource));
329 m_testCtx.getLog() << *m_program;
330 if (!m_program->isOk())
331 throw tcu::TestError("could not build program");
332
333 {
334 const tcu::Vec4 fullscreenQuad[] =
335 {
336 tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f),
337 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
338 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
339 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
340 };
341
342 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
343
344 gl.genBuffers(1, &m_bufID);
345 gl.bindBuffer(GL_ARRAY_BUFFER, m_bufID);
346 gl.bufferData(GL_ARRAY_BUFFER, sizeof(fullscreenQuad), fullscreenQuad, GL_STATIC_DRAW);
347 GLU_EXPECT_NO_ERROR(gl.getError(), "fill buffer");
348 }
349 }
350
deinit(void)351 void AttributeCase::deinit (void)
352 {
353 delete m_loader;
354 m_loader = DE_NULL;
355
356 delete m_program;
357 m_program = DE_NULL;
358
359 if (m_bufID)
360 {
361 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_bufID);
362 m_bufID = 0;
363 }
364 }
365
iterate(void)366 AttributeCase::IterateResult AttributeCase::iterate (void)
367 {
368 static const tcu::Vec4 testValues[] =
369 {
370 tcu::Vec4(0.0f, 0.5f, 0.2f, 1.0f),
371 tcu::Vec4(0.1f, 0.7f, 1.0f, 0.6f),
372 tcu::Vec4(0.4f, 0.2f, 0.0f, 0.5f),
373 tcu::Vec4(0.5f, 0.0f, 0.9f, 0.1f),
374 tcu::Vec4(0.6f, 0.2f, 0.2f, 0.9f),
375 tcu::Vec4(0.9f, 1.0f, 0.0f, 0.0f),
376 tcu::Vec4(1.0f, 0.5f, 0.3f, 0.8f),
377 };
378
379 const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", "Iteration " + de::toString(m_iteration+1) + "/" + de::toString(DE_LENGTH_OF_ARRAY(testValues)));
380
381 // Test normalizing transfers with whole range, non-normalizing with up to s_valueRange
382 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));
383
384 if (!renderWithValue(testValue))
385 m_allIterationsPassed = false;
386
387 // continue
388
389 if (++m_iteration < DE_LENGTH_OF_ARRAY(testValues))
390 return CONTINUE;
391
392 if (m_allIterationsPassed)
393 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
394 else
395 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected values");
396
397 return STOP;
398 }
399
genVertexSource(void) const400 std::string AttributeCase::genVertexSource (void) const
401 {
402 const int vectorSize = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::isDataTypeVector(m_dataType)) ? (glu::getDataTypeScalarSize(m_dataType)) : (-1);
403 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));
404 const int components = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType));
405 std::ostringstream buf;
406
407 buf << "#version 300 es\n"
408 "in highp vec4 a_position;\n"
409 "in highp " << glu::getDataTypeName(m_dataType) << " a_value;\n"
410 "out highp vec4 v_color;\n"
411 "void main (void)\n"
412 "{\n"
413 " gl_Position = a_position;\n"
414 "\n";
415
416 if (m_normalizing)
417 buf << " highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ");\n";
418 else
419 buf << " highp " << vectorType << " normalizedValue = " << ((glu::getDataTypeScalarType(m_dataType) == glu::TYPE_FLOAT) ? ("") : (vectorType)) << "(a_value" << ((glu::isDataTypeMatrix(m_dataType)) ? ("[1]") : ("")) << ") / float(" << s_valueRange << ");\n";
420
421 if (m_useNegativeValues)
422 buf << " highp " << vectorType << " positiveNormalizedValue = (normalizedValue + " << vectorType << "(1.0)) / 2.0;\n";
423 else
424 buf << " highp " << vectorType << " positiveNormalizedValue = normalizedValue;\n";
425
426 if (components == 1)
427 buf << " v_color = vec4(positiveNormalizedValue, 0.0, 0.0, 1.0);\n";
428 else if (components == 2)
429 buf << " v_color = vec4(positiveNormalizedValue.xy, 0.0, 1.0);\n";
430 else if (components == 3)
431 buf << " v_color = vec4(positiveNormalizedValue.xyz, 1.0);\n";
432 else if (components == 4)
433 buf << " v_color = vec4((positiveNormalizedValue.xy + positiveNormalizedValue.zz) / 2.0, positiveNormalizedValue.w, 1.0);\n";
434 else
435 DE_ASSERT(DE_FALSE);
436
437 buf << "}\n";
438
439 return buf.str();
440 }
441
renderWithValue(const tcu::Vec4 & v)442 bool AttributeCase::renderWithValue (const tcu::Vec4& v)
443 {
444 glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
445
446 gl.enableLogging(true);
447
448 const int positionIndex = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
449 const int valueIndex = gl.glGetAttribLocation(m_program->getProgram(), "a_value");
450 tcu::Surface dest (RENDER_SIZE, RENDER_SIZE);
451 tcu::Vec4 loadedValue;
452
453 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
454 gl.glClear(GL_COLOR_BUFFER_BIT);
455 gl.glViewport(0, 0, RENDER_SIZE, RENDER_SIZE);
456 GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
457
458 gl.glBindBuffer(GL_ARRAY_BUFFER, m_bufID);
459 gl.glVertexAttribPointer(positionIndex, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
460 gl.glEnableVertexAttribArray(positionIndex);
461 GLU_EXPECT_NO_ERROR(gl.glGetError(), "position va");
462
463 // transfer test value. Load to the second column in the matrix case
464 loadedValue = m_loader->load(gl, (glu::isDataTypeMatrix(m_dataType)) ? (valueIndex + 1) : (valueIndex), v);
465 GLU_EXPECT_NO_ERROR(gl.glGetError(), "default va");
466
467 gl.glUseProgram(m_program->getProgram());
468 gl.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
469 gl.glUseProgram(0);
470 GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
471
472 glu::readPixels(m_context.getRenderContext(), 0, 0, dest.getAccess());
473
474 // check whole result is colored correctly
475 return verifyUnicoloredBuffer(dest, computeColor(loadedValue));
476 }
477
computeColor(const tcu::Vec4 & value)478 tcu::Vec4 AttributeCase::computeColor (const tcu::Vec4& value)
479 {
480 const tcu::Vec4 normalizedValue = value / ((m_normalizing) ? (1.0f) : ((float)s_valueRange));
481 const tcu::Vec4 positiveNormalizedValue = ((m_useNegativeValues) ? ((normalizedValue + tcu::Vec4(1.0f)) / 2.0f) : (normalizedValue));
482 const int components = (glu::isDataTypeMatrix(m_dataType)) ? (glu::getDataTypeMatrixNumRows(m_dataType)) : (glu::getDataTypeScalarSize(m_dataType));
483
484 if (components == 1)
485 return tcu::Vec4(positiveNormalizedValue.x(), 0.0f, 0.0f, 1.0f);
486 else if (components == 2)
487 return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), 0.0f, 1.0f);
488 else if (components == 3)
489 return tcu::Vec4(positiveNormalizedValue.x(), positiveNormalizedValue.y(), positiveNormalizedValue.z(), 1.0f);
490 else if (components == 4)
491 return tcu::Vec4((positiveNormalizedValue.x() + positiveNormalizedValue.z()) / 2.0f, (positiveNormalizedValue.y() + positiveNormalizedValue.z()) / 2.0f, positiveNormalizedValue.w(), 1.0f);
492 else
493 DE_ASSERT(DE_FALSE);
494
495 return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
496 }
497
verifyUnicoloredBuffer(const tcu::Surface & scene,const tcu::Vec4 & refValue)498 bool AttributeCase::verifyUnicoloredBuffer (const tcu::Surface& scene, const tcu::Vec4& refValue)
499 {
500 tcu::Surface errorMask (RENDER_SIZE, RENDER_SIZE);
501 const tcu::RGBA refColor (refValue);
502 const int resultThreshold = 2;
503 const tcu::RGBA colorThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold() * resultThreshold;
504 bool error = false;
505
506 tcu::RGBA exampleColor;
507 tcu::IVec2 examplePos;
508
509 tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toIVec());
510
511 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying rendered image. Expecting color " << refColor << ", threshold " << colorThreshold << tcu::TestLog::EndMessage;
512
513 for (int y = 0; y < RENDER_SIZE; ++y)
514 for (int x = 0; x < RENDER_SIZE; ++x)
515 {
516 const tcu::RGBA color = scene.getPixel(x, y);
517
518 if (de::abs(color.getRed() - refColor.getRed()) > colorThreshold.getRed() ||
519 de::abs(color.getGreen() - refColor.getGreen()) > colorThreshold.getGreen() ||
520 de::abs(color.getBlue() - refColor.getBlue()) > colorThreshold.getBlue())
521 {
522 // first error
523 if (!error)
524 {
525 exampleColor = color;
526 examplePos = tcu::IVec2(x, y);
527 }
528
529 error = true;
530 errorMask.setPixel(x, y, tcu::RGBA::red());
531 }
532 }
533
534 if (!error)
535 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered image is valid." << tcu::TestLog::EndMessage;
536 else
537 {
538 m_testCtx.getLog() << tcu::TestLog::Message
539 << "Found invalid pixel(s).\n"
540 << "Pixel at (" << examplePos.x() << ", " << examplePos.y() << ") color: " << exampleColor
541 << tcu::TestLog::EndMessage
542 << tcu::TestLog::ImageSet("Result", "Render result")
543 << tcu::TestLog::Image("Result", "Result", scene)
544 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask)
545 << tcu::TestLog::EndImageSet;
546 }
547
548 return !error;
549 }
550
551 } // anonymous
552
DefaultVertexAttributeTests(Context & context)553 DefaultVertexAttributeTests::DefaultVertexAttributeTests (Context& context)
554 : TestCaseGroup(context, "default_vertex_attrib", "Test default vertex attributes")
555 {
556 }
557
~DefaultVertexAttributeTests(void)558 DefaultVertexAttributeTests::~DefaultVertexAttributeTests (void)
559 {
560 }
561
init(void)562 void DefaultVertexAttributeTests::init (void)
563 {
564 struct Target
565 {
566 const char* name;
567 glu::DataType dataType;
568 bool reducedTestSets; // !< use reduced coverage
569 };
570
571 static const Target floatTargets[] =
572 {
573 { "float", glu::TYPE_FLOAT, false },
574 { "vec2", glu::TYPE_FLOAT_VEC2, true },
575 { "vec3", glu::TYPE_FLOAT_VEC3, true },
576 { "vec4", glu::TYPE_FLOAT_VEC4, false },
577 { "mat2", glu::TYPE_FLOAT_MAT2, true },
578 { "mat2x3", glu::TYPE_FLOAT_MAT2X3, true },
579 { "mat2x4", glu::TYPE_FLOAT_MAT2X4, true },
580 { "mat3", glu::TYPE_FLOAT_MAT3, true },
581 { "mat3x2", glu::TYPE_FLOAT_MAT3X2, true },
582 { "mat3x4", glu::TYPE_FLOAT_MAT3X4, true },
583 { "mat4", glu::TYPE_FLOAT_MAT4, false },
584 { "mat4x2", glu::TYPE_FLOAT_MAT4X2, true },
585 { "mat4x3", glu::TYPE_FLOAT_MAT4X3, true },
586 };
587
588 static const Target intTargets[] =
589 {
590 { "int", glu::TYPE_INT, false },
591 { "ivec2", glu::TYPE_INT_VEC2, true },
592 { "ivec3", glu::TYPE_INT_VEC3, true },
593 { "ivec4", glu::TYPE_INT_VEC4, false },
594 };
595
596 static const Target uintTargets[] =
597 {
598 { "uint", glu::TYPE_UINT, false },
599 { "uvec2", glu::TYPE_UINT_VEC2, true },
600 { "uvec3", glu::TYPE_UINT_VEC3, true },
601 { "uvec4", glu::TYPE_UINT_VEC4, false },
602 };
603
604 // float targets
605
606 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(floatTargets); ++targetNdx)
607 {
608 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, floatTargets[targetNdx].name, (std::string("test with ") + floatTargets[targetNdx].name).c_str());
609 const bool fullSet = !floatTargets[targetNdx].reducedTestSets;
610
611 #define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, floatTargets[targetNdx].dataType))
612 #define ADD_REDUCED_CASE(X) if (fullSet) ADD_CASE(X)
613
614 ADD_CASE (LoaderVertexAttrib1f);
615 ADD_REDUCED_CASE(LoaderVertexAttrib2f);
616 ADD_REDUCED_CASE(LoaderVertexAttrib3f);
617 ADD_CASE (LoaderVertexAttrib4f);
618
619 ADD_CASE (LoaderVertexAttrib1fv);
620 ADD_REDUCED_CASE(LoaderVertexAttrib2fv);
621 ADD_REDUCED_CASE(LoaderVertexAttrib3fv);
622 ADD_CASE (LoaderVertexAttrib4fv);
623
624 #undef ADD_CASE
625 #undef ADD_REDUCED_CASE
626
627 addChild(group);
628 }
629
630 // int targets
631
632 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(intTargets); ++targetNdx)
633 {
634 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, intTargets[targetNdx].name, (std::string("test with ") + intTargets[targetNdx].name).c_str());
635
636 #define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, intTargets[targetNdx].dataType))
637
638 ADD_CASE (LoaderVertexAttribI4i);
639 ADD_CASE (LoaderVertexAttribI4iv);
640
641 #undef ADD_CASE
642
643 addChild(group);
644 }
645
646 // uint targets
647
648 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(uintTargets); ++targetNdx)
649 {
650 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, uintTargets[targetNdx].name, (std::string("test with ") + uintTargets[targetNdx].name).c_str());
651
652 #define ADD_CASE(X) group->addChild(AttributeCase::create<X>(m_context, uintTargets[targetNdx].dataType))
653
654 ADD_CASE (LoaderVertexAttribI4ui);
655 ADD_CASE (LoaderVertexAttribI4uiv);
656
657 #undef ADD_CASE
658
659 addChild(group);
660 }
661 }
662
663 } // Functional
664 } // gles3
665 } // deqp
666