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