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 42namespace deqp 43{ 44namespace gles3 45{ 46namespace Functional 47{ 48namespace 49{ 50 51static const int s_valueRange = 10; 52 53static 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 61template <typename T1, int S1, typename T2, int S2> 62tcu::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 78class FloatLoader 79{ 80public: 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 223GEN_DIRECT_FLOAT_LOADER(float, 1, f, "vertex_attrib_1f", (index, value.x())); 224GEN_DIRECT_FLOAT_LOADER(float, 2, f, "vertex_attrib_2f", (index, value.x(), value.y())); 225GEN_DIRECT_FLOAT_LOADER(float, 3, f, "vertex_attrib_3f", (index, value.x(), value.y(), value.z())); 226GEN_DIRECT_FLOAT_LOADER(float, 4, f, "vertex_attrib_4f", (index, value.x(), value.y(), value.z(), value.w())); 227 228GEN_INDIRECT_FLOAT_LOADER(float, 1, fv, "vertex_attrib_1fv"); 229GEN_INDIRECT_FLOAT_LOADER(float, 2, fv, "vertex_attrib_2fv"); 230GEN_INDIRECT_FLOAT_LOADER(float, 3, fv, "vertex_attrib_3fv"); 231GEN_INDIRECT_FLOAT_LOADER(float, 4, fv, "vertex_attrib_4fv"); 232 233GEN_DIRECT_INTEGER_LOADER(deInt32, 4, i, "vertex_attribi_4i", (index, value.x(), value.y(), value.z(), value.w())); 234GEN_INDIRECT_INTEGER_LOADER(deInt32, 4, iv, "vertex_attribi_4iv"); 235 236GEN_DIRECT_INTEGER_LOADER(deUint32, 4, ui, "vertex_attribi_4ui", (index, value.x(), value.y(), value.z(), value.w())); 237GEN_INDIRECT_INTEGER_LOADER(deUint32, 4, uiv, "vertex_attribi_4uiv"); 238 239class AttributeCase : public TestCase 240{ 241 AttributeCase (Context& ctx, const char* name, const char* desc, const char* funcName, bool normalizing, bool useNegative, glu::DataType dataType); 242public: 243 template<typename LoaderType> 244 static AttributeCase* create (Context& ctx, glu::DataType dataType); 245 ~AttributeCase (void); 246 247private: 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 274AttributeCase::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 288template<typename LoaderType> 289AttributeCase* 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 302AttributeCase::~AttributeCase (void) 303{ 304 deinit(); 305} 306 307void 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 351void 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 366AttributeCase::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 400std::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 442bool 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 478tcu::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 498bool 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 553DefaultVertexAttributeTests::DefaultVertexAttributeTests (Context& context) 554 : TestCaseGroup(context, "default_vertex_attrib", "Test default vertex attributes") 555{ 556} 557 558DefaultVertexAttributeTests::~DefaultVertexAttributeTests (void) 559{ 560} 561 562void 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