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 Shader indexing (arrays, vector, matrices) tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fShaderIndexingTests.hpp" 25 #include "glsShaderRenderCase.hpp" 26 #include "gluShaderUtil.hpp" 27 #include "tcuStringTemplate.hpp" 28 29 #include "deInt32.h" 30 #include "deMemory.h" 31 32 #include <map> 33 34 #include "glwEnums.hpp" 35 #include "glwFunctions.hpp" 36 37 using namespace std; 38 using namespace tcu; 39 using namespace glu; 40 using namespace deqp::gls; 41 42 namespace deqp 43 { 44 namespace gles2 45 { 46 namespace Functional 47 { 48 49 enum IndexAccessType 50 { 51 INDEXACCESS_STATIC = 0, 52 INDEXACCESS_DYNAMIC, 53 INDEXACCESS_STATIC_LOOP, 54 INDEXACCESS_DYNAMIC_LOOP, 55 56 INDEXACCESS_LAST 57 }; 58 59 static const char* getIndexAccessTypeName (IndexAccessType accessType) 60 { 61 static const char* s_names[INDEXACCESS_LAST] = 62 { 63 "static", 64 "dynamic", 65 "static_loop", 66 "dynamic_loop" 67 }; 68 69 DE_ASSERT(deInBounds32((int)accessType, 0, INDEXACCESS_LAST)); 70 return s_names[(int)accessType]; 71 } 72 73 enum VectorAccessType 74 { 75 DIRECT = 0, 76 COMPONENT, 77 SUBSCRIPT_STATIC, 78 SUBSCRIPT_DYNAMIC, 79 SUBSCRIPT_STATIC_LOOP, 80 SUBSCRIPT_DYNAMIC_LOOP, 81 82 VECTORACCESS_LAST 83 }; 84 85 static const char* getVectorAccessTypeName (VectorAccessType accessType) 86 { 87 static const char* s_names[VECTORACCESS_LAST] = 88 { 89 "direct", 90 "component", 91 "static_subscript", 92 "dynamic_subscript", 93 "static_loop_subscript", 94 "dynamic_loop_subscript" 95 }; 96 97 DE_ASSERT(deInBounds32((int)accessType, 0, VECTORACCESS_LAST)); 98 return s_names[(int)accessType]; 99 } 100 101 enum RequirementFlags 102 { 103 REQUIREMENT_UNIFORM_INDEXING = (1<<0), 104 REQUIREMENT_VERTEX_UNIFORM_LOOPS = (1<<1), 105 REQUIREMENT_FRAGMENT_UNIFORM_LOOPS = (1<<2), 106 }; 107 108 void evalArrayCoordsFloat (ShaderEvalContext& c) { c.color.x() = 1.875f * c.coords.x(); } 109 void evalArrayCoordsVec2 (ShaderEvalContext& c) { c.color.xy() = 1.875f * c.coords.swizzle(0,1); } 110 void evalArrayCoordsVec3 (ShaderEvalContext& c) { c.color.xyz() = 1.875f * c.coords.swizzle(0,1,2); } 111 void evalArrayCoordsVec4 (ShaderEvalContext& c) { c.color = 1.875f * c.coords; } 112 113 static ShaderEvalFunc getArrayCoordsEvalFunc (DataType dataType) 114 { 115 if (dataType == TYPE_FLOAT) return evalArrayCoordsFloat; 116 else if (dataType == TYPE_FLOAT_VEC2) return evalArrayCoordsVec2; 117 else if (dataType == TYPE_FLOAT_VEC3) return evalArrayCoordsVec3; 118 else if (dataType == TYPE_FLOAT_VEC4) return evalArrayCoordsVec4; 119 120 DE_ASSERT(!"Invalid data type."); 121 return NULL; 122 } 123 124 void evalArrayUniformFloat (ShaderEvalContext& c) { c.color.x() = 1.875f * c.constCoords.x(); } 125 void evalArrayUniformVec2 (ShaderEvalContext& c) { c.color.xy() = 1.875f * c.constCoords.swizzle(0,1); } 126 void evalArrayUniformVec3 (ShaderEvalContext& c) { c.color.xyz() = 1.875f * c.constCoords.swizzle(0,1,2); } 127 void evalArrayUniformVec4 (ShaderEvalContext& c) { c.color = 1.875f * c.constCoords; } 128 129 static ShaderEvalFunc getArrayUniformEvalFunc (DataType dataType) 130 { 131 if (dataType == TYPE_FLOAT) return evalArrayUniformFloat; 132 else if (dataType == TYPE_FLOAT_VEC2) return evalArrayUniformVec2; 133 else if (dataType == TYPE_FLOAT_VEC3) return evalArrayUniformVec3; 134 else if (dataType == TYPE_FLOAT_VEC4) return evalArrayUniformVec4; 135 136 DE_ASSERT(!"Invalid data type."); 137 return NULL; 138 } 139 140 // ShaderIndexingCase 141 142 class ShaderIndexingCase : public ShaderRenderCase 143 { 144 public: 145 ShaderIndexingCase (Context& context, const char* name, const char* description, bool isVertexCase, DataType varType, ShaderEvalFunc evalFunc, deUint32 requirements, const char* vertShaderSource, const char* fragShaderSource); 146 virtual ~ShaderIndexingCase (void); 147 148 virtual void init (void); 149 150 private: 151 ShaderIndexingCase (const ShaderIndexingCase&); // not allowed! 152 ShaderIndexingCase& operator= (const ShaderIndexingCase&); // not allowed! 153 154 virtual void setup (int programID); 155 virtual void setupUniforms (int programID, const Vec4& constCoords); 156 157 DataType m_varType; 158 deUint32 m_requirements; 159 }; 160 161 ShaderIndexingCase::ShaderIndexingCase (Context& context, const char* name, const char* description, bool isVertexCase, DataType varType, ShaderEvalFunc evalFunc, deUint32 requirements, const char* vertShaderSource, const char* fragShaderSource) 162 : ShaderRenderCase (context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc) 163 , m_requirements (requirements) 164 { 165 m_varType = varType; 166 m_vertShaderSource = vertShaderSource; 167 m_fragShaderSource = fragShaderSource; 168 } 169 170 ShaderIndexingCase::~ShaderIndexingCase (void) 171 { 172 } 173 174 void ShaderIndexingCase::init (void) 175 { 176 const bool isSupported = !(m_requirements & REQUIREMENT_UNIFORM_INDEXING) && 177 (!(m_requirements & REQUIREMENT_VERTEX_UNIFORM_LOOPS) || m_ctxInfo.isVertexUniformLoopSupported()) && 178 (!(m_requirements & REQUIREMENT_FRAGMENT_UNIFORM_LOOPS) || m_ctxInfo.isFragmentUniformLoopSupported()); 179 180 try 181 { 182 ShaderRenderCase::init(); 183 } 184 catch (const CompileFailed&) 185 { 186 if (!isSupported) 187 throw tcu::NotSupportedError("Shader is not supported"); 188 else 189 throw; 190 } 191 } 192 193 void ShaderIndexingCase::setup (int programID) 194 { 195 DE_UNREF(programID); 196 } 197 198 void ShaderIndexingCase::setupUniforms (int programID, const Vec4& constCoords) 199 { 200 const glw::Functions& gl = m_renderCtx.getFunctions(); 201 202 DE_UNREF(constCoords); 203 204 int arrLoc = gl.getUniformLocation(programID, "u_arr"); 205 if (arrLoc != -1) 206 { 207 //int scalarSize = getDataTypeScalarSize(m_varType); 208 if (m_varType == TYPE_FLOAT) 209 { 210 float arr[4]; 211 arr[0] = constCoords.x(); 212 arr[1] = constCoords.x() * 0.5f; 213 arr[2] = constCoords.x() * 0.25f; 214 arr[3] = constCoords.x() * 0.125f; 215 gl.uniform1fv(arrLoc, 4, &arr[0]); 216 } 217 else if (m_varType == TYPE_FLOAT_VEC2) 218 { 219 Vec2 arr[4]; 220 arr[0] = constCoords.swizzle(0,1); 221 arr[1] = constCoords.swizzle(0,1) * 0.5f; 222 arr[2] = constCoords.swizzle(0,1) * 0.25f; 223 arr[3] = constCoords.swizzle(0,1) * 0.125f; 224 gl.uniform2fv(arrLoc, 4, arr[0].getPtr()); 225 } 226 else if (m_varType == TYPE_FLOAT_VEC3) 227 { 228 Vec3 arr[4]; 229 arr[0] = constCoords.swizzle(0,1,2); 230 arr[1] = constCoords.swizzle(0,1,2) * 0.5f; 231 arr[2] = constCoords.swizzle(0,1,2) * 0.25f; 232 arr[3] = constCoords.swizzle(0,1,2) * 0.125f; 233 gl.uniform3fv(arrLoc, 4, arr[0].getPtr()); 234 } 235 else if (m_varType == TYPE_FLOAT_VEC4) 236 { 237 Vec4 arr[4]; 238 arr[0] = constCoords.swizzle(0,1,2,3); 239 arr[1] = constCoords.swizzle(0,1,2,3) * 0.5f; 240 arr[2] = constCoords.swizzle(0,1,2,3) * 0.25f; 241 arr[3] = constCoords.swizzle(0,1,2,3) * 0.125f; 242 gl.uniform4fv(arrLoc, 4, arr[0].getPtr()); 243 } 244 else 245 throw tcu::TestError("u_arr should not have location assigned in this test case"); 246 } 247 } 248 249 // Helpers. 250 251 static ShaderIndexingCase* createVaryingArrayCase (Context& context, const char* caseName, const char* description, DataType varType, IndexAccessType vertAccess, IndexAccessType fragAccess) 252 { 253 std::ostringstream vtx; 254 vtx << "attribute highp vec4 a_position;\n"; 255 vtx << "attribute highp vec4 a_coords;\n"; 256 if (vertAccess == INDEXACCESS_DYNAMIC) 257 vtx << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n"; 258 else if (vertAccess == INDEXACCESS_DYNAMIC_LOOP) 259 vtx << "uniform mediump int ui_four;\n"; 260 vtx << "varying ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n"; 261 vtx << "\n"; 262 vtx << "void main()\n"; 263 vtx << "{\n"; 264 vtx << " gl_Position = a_position;\n"; 265 if (vertAccess == INDEXACCESS_STATIC) 266 { 267 vtx << " var[0] = ${VAR_TYPE}(a_coords);\n"; 268 vtx << " var[1] = ${VAR_TYPE}(a_coords) * 0.5;\n"; 269 vtx << " var[2] = ${VAR_TYPE}(a_coords) * 0.25;\n"; 270 vtx << " var[3] = ${VAR_TYPE}(a_coords) * 0.125;\n"; 271 } 272 else if (vertAccess == INDEXACCESS_DYNAMIC) 273 { 274 vtx << " var[ui_zero] = ${VAR_TYPE}(a_coords);\n"; 275 vtx << " var[ui_one] = ${VAR_TYPE}(a_coords) * 0.5;\n"; 276 vtx << " var[ui_two] = ${VAR_TYPE}(a_coords) * 0.25;\n"; 277 vtx << " var[ui_three] = ${VAR_TYPE}(a_coords) * 0.125;\n"; 278 } 279 else if (vertAccess == INDEXACCESS_STATIC_LOOP) 280 { 281 vtx << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n"; 282 vtx << " for (int i = 0; i < 4; i++)\n"; 283 vtx << " {\n"; 284 vtx << " var[i] = ${VAR_TYPE}(coords);\n"; 285 vtx << " coords = coords * 0.5;\n"; 286 vtx << " }\n"; 287 } 288 else 289 { 290 DE_ASSERT(vertAccess == INDEXACCESS_DYNAMIC_LOOP); 291 vtx << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n"; 292 vtx << " for (int i = 0; i < ui_four; i++)\n"; 293 vtx << " {\n"; 294 vtx << " var[i] = ${VAR_TYPE}(coords);\n"; 295 vtx << " coords = coords * 0.5;\n"; 296 vtx << " }\n"; 297 } 298 vtx << "}\n"; 299 300 std::ostringstream frag; 301 frag << "precision mediump int;\n"; 302 if (fragAccess == INDEXACCESS_DYNAMIC) 303 frag << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n"; 304 else if (fragAccess == INDEXACCESS_DYNAMIC_LOOP) 305 frag << "uniform int ui_four;\n"; 306 frag << "varying ${PRECISION} ${VAR_TYPE} var[${ARRAY_LEN}];\n"; 307 frag << "\n"; 308 frag << "void main()\n"; 309 frag << "{\n"; 310 frag << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n"; 311 if (fragAccess == INDEXACCESS_STATIC) 312 { 313 frag << " res += var[0];\n"; 314 frag << " res += var[1];\n"; 315 frag << " res += var[2];\n"; 316 frag << " res += var[3];\n"; 317 } 318 else if (fragAccess == INDEXACCESS_DYNAMIC) 319 { 320 frag << " res += var[ui_zero];\n"; 321 frag << " res += var[ui_one];\n"; 322 frag << " res += var[ui_two];\n"; 323 frag << " res += var[ui_three];\n"; 324 } 325 else if (fragAccess == INDEXACCESS_STATIC_LOOP) 326 { 327 frag << " for (int i = 0; i < 4; i++)\n"; 328 frag << " res += var[i];\n"; 329 } 330 else 331 { 332 DE_ASSERT(fragAccess == INDEXACCESS_DYNAMIC_LOOP); 333 frag << " for (int i = 0; i < ui_four; i++)\n"; 334 frag << " res += var[i];\n"; 335 } 336 frag << " gl_FragColor = vec4(res${PADDING});\n"; 337 frag << "}\n"; 338 339 // Fill in shader templates. 340 map<string, string> params; 341 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType))); 342 params.insert(pair<string, string>("ARRAY_LEN", "4")); 343 params.insert(pair<string, string>("PRECISION", "mediump")); 344 345 if (varType == TYPE_FLOAT) 346 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0")); 347 else if (varType == TYPE_FLOAT_VEC2) 348 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0")); 349 else if (varType == TYPE_FLOAT_VEC3) 350 params.insert(pair<string, string>("PADDING", ", 1.0")); 351 else 352 params.insert(pair<string, string>("PADDING", "")); 353 354 StringTemplate vertTemplate(vtx.str().c_str()); 355 StringTemplate fragTemplate(frag.str().c_str()); 356 string vertexShaderSource = vertTemplate.specialize(params); 357 string fragmentShaderSource = fragTemplate.specialize(params); 358 359 ShaderEvalFunc evalFunc = getArrayCoordsEvalFunc(varType); 360 deUint32 requirements = 0; 361 362 if (vertAccess == INDEXACCESS_DYNAMIC || fragAccess == INDEXACCESS_DYNAMIC) 363 requirements |= REQUIREMENT_UNIFORM_INDEXING; 364 365 if (vertAccess == INDEXACCESS_DYNAMIC_LOOP) 366 requirements |= REQUIREMENT_VERTEX_UNIFORM_LOOPS|REQUIREMENT_UNIFORM_INDEXING; 367 368 if (fragAccess == INDEXACCESS_DYNAMIC_LOOP) 369 requirements |= REQUIREMENT_FRAGMENT_UNIFORM_LOOPS|REQUIREMENT_UNIFORM_INDEXING; 370 371 return new ShaderIndexingCase(context, caseName, description, true, varType, evalFunc, requirements, vertexShaderSource.c_str(), fragmentShaderSource.c_str()); 372 } 373 374 static ShaderIndexingCase* createUniformArrayCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, IndexAccessType readAccess) 375 { 376 std::ostringstream vtx; 377 std::ostringstream frag; 378 std::ostringstream& op = isVertexCase ? vtx : frag; 379 380 vtx << "attribute highp vec4 a_position;\n"; 381 vtx << "attribute highp vec4 a_coords;\n"; 382 383 if (isVertexCase) 384 { 385 vtx << "varying mediump vec4 v_color;\n"; 386 frag << "varying mediump vec4 v_color;\n"; 387 } 388 else 389 { 390 vtx << "varying mediump vec4 v_coords;\n"; 391 frag << "varying mediump vec4 v_coords;\n"; 392 } 393 394 if (readAccess == INDEXACCESS_DYNAMIC) 395 op << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n"; 396 else if (readAccess == INDEXACCESS_DYNAMIC_LOOP) 397 op << "uniform mediump int ui_four;\n"; 398 399 op << "uniform ${PRECISION} ${VAR_TYPE} u_arr[${ARRAY_LEN}];\n"; 400 401 vtx << "\n"; 402 vtx << "void main()\n"; 403 vtx << "{\n"; 404 vtx << " gl_Position = a_position;\n"; 405 406 frag << "\n"; 407 frag << "void main()\n"; 408 frag << "{\n"; 409 410 // Read array. 411 op << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n"; 412 if (readAccess == INDEXACCESS_STATIC) 413 { 414 op << " res += u_arr[0];\n"; 415 op << " res += u_arr[1];\n"; 416 op << " res += u_arr[2];\n"; 417 op << " res += u_arr[3];\n"; 418 } 419 else if (readAccess == INDEXACCESS_DYNAMIC) 420 { 421 op << " res += u_arr[ui_zero];\n"; 422 op << " res += u_arr[ui_one];\n"; 423 op << " res += u_arr[ui_two];\n"; 424 op << " res += u_arr[ui_three];\n"; 425 } 426 else if (readAccess == INDEXACCESS_STATIC_LOOP) 427 { 428 op << " for (int i = 0; i < 4; i++)\n"; 429 op << " res += u_arr[i];\n"; 430 } 431 else 432 { 433 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP); 434 op << " for (int i = 0; i < ui_four; i++)\n"; 435 op << " res += u_arr[i];\n"; 436 } 437 438 if (isVertexCase) 439 { 440 vtx << " v_color = vec4(res${PADDING});\n"; 441 frag << " gl_FragColor = v_color;\n"; 442 } 443 else 444 { 445 vtx << " v_coords = a_coords;\n"; 446 frag << " gl_FragColor = vec4(res${PADDING});\n"; 447 } 448 449 vtx << "}\n"; 450 frag << "}\n"; 451 452 // Fill in shader templates. 453 map<string, string> params; 454 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType))); 455 params.insert(pair<string, string>("ARRAY_LEN", "4")); 456 params.insert(pair<string, string>("PRECISION", "mediump")); 457 458 if (varType == TYPE_FLOAT) 459 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0")); 460 else if (varType == TYPE_FLOAT_VEC2) 461 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0")); 462 else if (varType == TYPE_FLOAT_VEC3) 463 params.insert(pair<string, string>("PADDING", ", 1.0")); 464 else 465 params.insert(pair<string, string>("PADDING", "")); 466 467 StringTemplate vertTemplate(vtx.str().c_str()); 468 StringTemplate fragTemplate(frag.str().c_str()); 469 string vertexShaderSource = vertTemplate.specialize(params); 470 string fragmentShaderSource = fragTemplate.specialize(params); 471 472 ShaderEvalFunc evalFunc = getArrayUniformEvalFunc(varType); 473 deUint32 requirements = 0; 474 475 if (readAccess == INDEXACCESS_DYNAMIC) 476 requirements |= REQUIREMENT_UNIFORM_INDEXING; 477 478 if (readAccess == INDEXACCESS_DYNAMIC_LOOP) 479 requirements |= (isVertexCase ? REQUIREMENT_VERTEX_UNIFORM_LOOPS : REQUIREMENT_FRAGMENT_UNIFORM_LOOPS) | REQUIREMENT_UNIFORM_INDEXING; 480 481 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, requirements, vertexShaderSource.c_str(), fragmentShaderSource.c_str()); 482 } 483 484 static ShaderIndexingCase* createTmpArrayCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, IndexAccessType writeAccess, IndexAccessType readAccess) 485 { 486 std::ostringstream vtx; 487 std::ostringstream frag; 488 std::ostringstream& op = isVertexCase ? vtx : frag; 489 490 vtx << "attribute highp vec4 a_position;\n"; 491 vtx << "attribute highp vec4 a_coords;\n"; 492 493 if (isVertexCase) 494 { 495 vtx << "varying mediump vec4 v_color;\n"; 496 frag << "varying mediump vec4 v_color;\n"; 497 } 498 else 499 { 500 vtx << "varying mediump vec4 v_coords;\n"; 501 frag << "varying mediump vec4 v_coords;\n"; 502 } 503 504 if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC) 505 op << "uniform mediump int ui_zero, ui_one, ui_two, ui_three;\n"; 506 507 if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP) 508 op << "uniform mediump int ui_four;\n"; 509 510 vtx << "\n"; 511 vtx << "void main()\n"; 512 vtx << "{\n"; 513 vtx << " gl_Position = a_position;\n"; 514 515 frag << "\n"; 516 frag << "void main()\n"; 517 frag << "{\n"; 518 519 // Write array. 520 if (isVertexCase) 521 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n"; 522 else 523 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n"; 524 525 op << " ${PRECISION} ${VAR_TYPE} arr[${ARRAY_LEN}];\n"; 526 if (writeAccess == INDEXACCESS_STATIC) 527 { 528 op << " arr[0] = ${VAR_TYPE}(coords);\n"; 529 op << " arr[1] = ${VAR_TYPE}(coords) * 0.5;\n"; 530 op << " arr[2] = ${VAR_TYPE}(coords) * 0.25;\n"; 531 op << " arr[3] = ${VAR_TYPE}(coords) * 0.125;\n"; 532 } 533 else if (writeAccess == INDEXACCESS_DYNAMIC) 534 { 535 op << " arr[ui_zero] = ${VAR_TYPE}(coords);\n"; 536 op << " arr[ui_one] = ${VAR_TYPE}(coords) * 0.5;\n"; 537 op << " arr[ui_two] = ${VAR_TYPE}(coords) * 0.25;\n"; 538 op << " arr[ui_three] = ${VAR_TYPE}(coords) * 0.125;\n"; 539 } 540 else if (writeAccess == INDEXACCESS_STATIC_LOOP) 541 { 542 op << " for (int i = 0; i < 4; i++)\n"; 543 op << " {\n"; 544 op << " arr[i] = ${VAR_TYPE}(coords);\n"; 545 op << " coords = coords * 0.5;\n"; 546 op << " }\n"; 547 } 548 else 549 { 550 DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP); 551 op << " for (int i = 0; i < ui_four; i++)\n"; 552 op << " {\n"; 553 op << " arr[i] = ${VAR_TYPE}(coords);\n"; 554 op << " coords = coords * 0.5;\n"; 555 op << " }\n"; 556 } 557 558 // Read array. 559 op << " ${PRECISION} ${VAR_TYPE} res = ${VAR_TYPE}(0.0);\n"; 560 if (readAccess == INDEXACCESS_STATIC) 561 { 562 op << " res += arr[0];\n"; 563 op << " res += arr[1];\n"; 564 op << " res += arr[2];\n"; 565 op << " res += arr[3];\n"; 566 } 567 else if (readAccess == INDEXACCESS_DYNAMIC) 568 { 569 op << " res += arr[ui_zero];\n"; 570 op << " res += arr[ui_one];\n"; 571 op << " res += arr[ui_two];\n"; 572 op << " res += arr[ui_three];\n"; 573 } 574 else if (readAccess == INDEXACCESS_STATIC_LOOP) 575 { 576 op << " for (int i = 0; i < 4; i++)\n"; 577 op << " res += arr[i];\n"; 578 } 579 else 580 { 581 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP); 582 op << " for (int i = 0; i < ui_four; i++)\n"; 583 op << " res += arr[i];\n"; 584 } 585 586 if (isVertexCase) 587 { 588 vtx << " v_color = vec4(res${PADDING});\n"; 589 frag << " gl_FragColor = v_color;\n"; 590 } 591 else 592 { 593 vtx << " v_coords = a_coords;\n"; 594 frag << " gl_FragColor = vec4(res${PADDING});\n"; 595 } 596 597 vtx << "}\n"; 598 frag << "}\n"; 599 600 // Fill in shader templates. 601 map<string, string> params; 602 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType))); 603 params.insert(pair<string, string>("ARRAY_LEN", "4")); 604 params.insert(pair<string, string>("PRECISION", "mediump")); 605 606 if (varType == TYPE_FLOAT) 607 params.insert(pair<string, string>("PADDING", ", 0.0, 0.0, 1.0")); 608 else if (varType == TYPE_FLOAT_VEC2) 609 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0")); 610 else if (varType == TYPE_FLOAT_VEC3) 611 params.insert(pair<string, string>("PADDING", ", 1.0")); 612 else 613 params.insert(pair<string, string>("PADDING", "")); 614 615 StringTemplate vertTemplate(vtx.str().c_str()); 616 StringTemplate fragTemplate(frag.str().c_str()); 617 string vertexShaderSource = vertTemplate.specialize(params); 618 string fragmentShaderSource = fragTemplate.specialize(params); 619 620 ShaderEvalFunc evalFunc = getArrayCoordsEvalFunc(varType); 621 deUint32 requirements = 0; 622 623 if (readAccess == INDEXACCESS_DYNAMIC || writeAccess == INDEXACCESS_DYNAMIC) 624 requirements |= REQUIREMENT_UNIFORM_INDEXING; 625 626 if (readAccess == INDEXACCESS_DYNAMIC_LOOP || writeAccess == INDEXACCESS_DYNAMIC_LOOP) 627 requirements |= (isVertexCase ? REQUIREMENT_VERTEX_UNIFORM_LOOPS : REQUIREMENT_FRAGMENT_UNIFORM_LOOPS) | REQUIREMENT_UNIFORM_INDEXING; 628 629 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, requirements, vertexShaderSource.c_str(), fragmentShaderSource.c_str()); 630 } 631 632 // VECTOR SUBSCRIPT. 633 634 void evalSubscriptVec2 (ShaderEvalContext& c) { c.color.xyz() = Vec3(c.coords.x() + 0.5f*c.coords.y()); } 635 void evalSubscriptVec3 (ShaderEvalContext& c) { c.color.xyz() = Vec3(c.coords.x() + 0.5f*c.coords.y() + 0.25f*c.coords.z()); } 636 void evalSubscriptVec4 (ShaderEvalContext& c) { c.color.xyz() = Vec3(c.coords.x() + 0.5f*c.coords.y() + 0.25f*c.coords.z() + 0.125f*c.coords.w()); } 637 638 static ShaderEvalFunc getVectorSubscriptEvalFunc (DataType dataType) 639 { 640 if (dataType == TYPE_FLOAT_VEC2) return evalSubscriptVec2; 641 else if (dataType == TYPE_FLOAT_VEC3) return evalSubscriptVec3; 642 else if (dataType == TYPE_FLOAT_VEC4) return evalSubscriptVec4; 643 644 DE_ASSERT(!"Invalid data type."); 645 return NULL; 646 } 647 648 static ShaderIndexingCase* createVectorSubscriptCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, VectorAccessType writeAccess, VectorAccessType readAccess) 649 { 650 std::ostringstream vtx; 651 std::ostringstream frag; 652 std::ostringstream& op = isVertexCase ? vtx : frag; 653 654 int vecLen = getDataTypeScalarSize(varType); 655 const char* vecLenName = getIntUniformName(vecLen); 656 657 vtx << "attribute highp vec4 a_position;\n"; 658 vtx << "attribute highp vec4 a_coords;\n"; 659 660 if (isVertexCase) 661 { 662 vtx << "varying mediump vec3 v_color;\n"; 663 frag << "varying mediump vec3 v_color;\n"; 664 } 665 else 666 { 667 vtx << "varying mediump vec4 v_coords;\n"; 668 frag << "varying mediump vec4 v_coords;\n"; 669 } 670 671 if (writeAccess == SUBSCRIPT_DYNAMIC || readAccess == SUBSCRIPT_DYNAMIC) 672 { 673 op << "uniform mediump int ui_zero"; 674 if (vecLen >= 2) op << ", ui_one"; 675 if (vecLen >= 3) op << ", ui_two"; 676 if (vecLen >= 4) op << ", ui_three"; 677 op << ";\n"; 678 } 679 680 if (writeAccess == SUBSCRIPT_DYNAMIC_LOOP || readAccess == SUBSCRIPT_DYNAMIC_LOOP) 681 op << "uniform mediump int " << vecLenName << ";\n"; 682 683 vtx << "\n"; 684 vtx << "void main()\n"; 685 vtx << "{\n"; 686 vtx << " gl_Position = a_position;\n"; 687 688 frag << "\n"; 689 frag << "void main()\n"; 690 frag << "{\n"; 691 692 // Write vector. 693 if (isVertexCase) 694 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(a_coords);\n"; 695 else 696 op << " ${PRECISION} ${VAR_TYPE} coords = ${VAR_TYPE}(v_coords);\n"; 697 698 op << " ${PRECISION} ${VAR_TYPE} tmp;\n"; 699 if (writeAccess == DIRECT) 700 op << " tmp = coords.${SWIZZLE} * vec4(1.0, 0.5, 0.25, 0.125).${SWIZZLE};\n"; 701 else if (writeAccess == COMPONENT) 702 { 703 op << " tmp.x = coords.x;\n"; 704 if (vecLen >= 2) op << " tmp.y = coords.y * 0.5;\n"; 705 if (vecLen >= 3) op << " tmp.z = coords.z * 0.25;\n"; 706 if (vecLen >= 4) op << " tmp.w = coords.w * 0.125;\n"; 707 } 708 else if (writeAccess == SUBSCRIPT_STATIC) 709 { 710 op << " tmp[0] = coords.x;\n"; 711 if (vecLen >= 2) op << " tmp[1] = coords.y * 0.5;\n"; 712 if (vecLen >= 3) op << " tmp[2] = coords.z * 0.25;\n"; 713 if (vecLen >= 4) op << " tmp[3] = coords.w * 0.125;\n"; 714 } 715 else if (writeAccess == SUBSCRIPT_DYNAMIC) 716 { 717 op << " tmp[ui_zero] = coords.x;\n"; 718 if (vecLen >= 2) op << " tmp[ui_one] = coords.y * 0.5;\n"; 719 if (vecLen >= 3) op << " tmp[ui_two] = coords.z * 0.25;\n"; 720 if (vecLen >= 4) op << " tmp[ui_three] = coords.w * 0.125;\n"; 721 } 722 else if (writeAccess == SUBSCRIPT_STATIC_LOOP) 723 { 724 op << " for (int i = 0; i < " << vecLen << "; i++)\n"; 725 op << " {\n"; 726 op << " tmp[i] = coords.x;\n"; 727 op << " coords = coords.${ROT_SWIZZLE} * 0.5;\n"; 728 op << " }\n"; 729 } 730 else 731 { 732 DE_ASSERT(writeAccess == SUBSCRIPT_DYNAMIC_LOOP); 733 op << " for (int i = 0; i < " << vecLenName << "; i++)\n"; 734 op << " {\n"; 735 op << " tmp[i] = coords.x;\n"; 736 op << " coords = coords.${ROT_SWIZZLE} * 0.5;\n"; 737 op << " }\n"; 738 } 739 740 // Read vector. 741 op << " ${PRECISION} float res = 0.0;\n"; 742 if (readAccess == DIRECT) 743 op << " res = dot(tmp, ${VAR_TYPE}(1.0));\n"; 744 else if (readAccess == COMPONENT) 745 { 746 op << " res += tmp.x;\n"; 747 if (vecLen >= 2) op << " res += tmp.y;\n"; 748 if (vecLen >= 3) op << " res += tmp.z;\n"; 749 if (vecLen >= 4) op << " res += tmp.w;\n"; 750 } 751 else if (readAccess == SUBSCRIPT_STATIC) 752 { 753 op << " res += tmp[0];\n"; 754 if (vecLen >= 2) op << " res += tmp[1];\n"; 755 if (vecLen >= 3) op << " res += tmp[2];\n"; 756 if (vecLen >= 4) op << " res += tmp[3];\n"; 757 } 758 else if (readAccess == SUBSCRIPT_DYNAMIC) 759 { 760 op << " res += tmp[ui_zero];\n"; 761 if (vecLen >= 2) op << " res += tmp[ui_one];\n"; 762 if (vecLen >= 3) op << " res += tmp[ui_two];\n"; 763 if (vecLen >= 4) op << " res += tmp[ui_three];\n"; 764 } 765 else if (readAccess == SUBSCRIPT_STATIC_LOOP) 766 { 767 op << " for (int i = 0; i < " << vecLen << "; i++)\n"; 768 op << " res += tmp[i];\n"; 769 } 770 else 771 { 772 DE_ASSERT(readAccess == SUBSCRIPT_DYNAMIC_LOOP); 773 op << " for (int i = 0; i < " << vecLenName << "; i++)\n"; 774 op << " res += tmp[i];\n"; 775 } 776 777 if (isVertexCase) 778 { 779 vtx << " v_color = vec3(res);\n"; 780 frag << " gl_FragColor = vec4(v_color, 1.0);\n"; 781 } 782 else 783 { 784 vtx << " v_coords = a_coords;\n"; 785 frag << " gl_FragColor = vec4(vec3(res), 1.0);\n"; 786 } 787 788 vtx << "}\n"; 789 frag << "}\n"; 790 791 // Fill in shader templates. 792 static const char* s_swizzles[5] = { "", "x", "xy", "xyz", "xyzw" }; 793 static const char* s_rotSwizzles[5] = { "", "x", "yx", "yzx", "yzwx" }; 794 795 map<string, string> params; 796 params.insert(pair<string, string>("VAR_TYPE", getDataTypeName(varType))); 797 params.insert(pair<string, string>("PRECISION", "mediump")); 798 params.insert(pair<string, string>("SWIZZLE", s_swizzles[vecLen])); 799 params.insert(pair<string, string>("ROT_SWIZZLE", s_rotSwizzles[vecLen])); 800 801 StringTemplate vertTemplate(vtx.str().c_str()); 802 StringTemplate fragTemplate(frag.str().c_str()); 803 string vertexShaderSource = vertTemplate.specialize(params); 804 string fragmentShaderSource = fragTemplate.specialize(params); 805 806 ShaderEvalFunc evalFunc = getVectorSubscriptEvalFunc(varType); 807 deUint32 requirements = 0; 808 809 if (readAccess == SUBSCRIPT_DYNAMIC || writeAccess == SUBSCRIPT_DYNAMIC) 810 requirements |= REQUIREMENT_UNIFORM_INDEXING; 811 812 if (readAccess == SUBSCRIPT_DYNAMIC_LOOP || writeAccess == SUBSCRIPT_DYNAMIC_LOOP) 813 requirements |= (isVertexCase ? REQUIREMENT_VERTEX_UNIFORM_LOOPS : REQUIREMENT_FRAGMENT_UNIFORM_LOOPS) | REQUIREMENT_UNIFORM_INDEXING; 814 815 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, requirements, vertexShaderSource.c_str(), fragmentShaderSource.c_str()); 816 } 817 818 // MATRIX SUBSCRIPT. 819 820 void evalSubscriptMat2 (ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1) + 0.5f*c.coords.swizzle(1,2); } 821 void evalSubscriptMat3 (ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2) + 0.5f*c.coords.swizzle(1,2,3) + 0.25f*c.coords.swizzle(2,3,0); } 822 void evalSubscriptMat4 (ShaderEvalContext& c) { c.color = c.coords + 0.5f*c.coords.swizzle(1,2,3,0) + 0.25f*c.coords.swizzle(2,3,0,1) + 0.125f*c.coords.swizzle(3,0,1,2); } 823 824 static ShaderEvalFunc getMatrixSubscriptEvalFunc (DataType dataType) 825 { 826 if (dataType == TYPE_FLOAT_MAT2) return evalSubscriptMat2; 827 else if (dataType == TYPE_FLOAT_MAT3) return evalSubscriptMat3; 828 else if (dataType == TYPE_FLOAT_MAT4) return evalSubscriptMat4; 829 830 DE_ASSERT(!"Invalid data type."); 831 return NULL; 832 } 833 834 static ShaderIndexingCase* createMatrixSubscriptCase (Context& context, const char* caseName, const char* description, bool isVertexCase, DataType varType, IndexAccessType writeAccess, IndexAccessType readAccess) 835 { 836 std::ostringstream vtx; 837 std::ostringstream frag; 838 std::ostringstream& op = isVertexCase ? vtx : frag; 839 840 int matSize = getDataTypeMatrixNumRows(varType); 841 const char* matSizeName = getIntUniformName(matSize); 842 DataType vecType = getDataTypeFloatVec(matSize); 843 844 vtx << "attribute highp vec4 a_position;\n"; 845 vtx << "attribute highp vec4 a_coords;\n"; 846 847 if (isVertexCase) 848 { 849 vtx << "varying mediump vec4 v_color;\n"; 850 frag << "varying mediump vec4 v_color;\n"; 851 } 852 else 853 { 854 vtx << "varying mediump vec4 v_coords;\n"; 855 frag << "varying mediump vec4 v_coords;\n"; 856 } 857 858 if (writeAccess == INDEXACCESS_DYNAMIC || readAccess == INDEXACCESS_DYNAMIC) 859 { 860 op << "uniform mediump int ui_zero"; 861 if (matSize >= 2) op << ", ui_one"; 862 if (matSize >= 3) op << ", ui_two"; 863 if (matSize >= 4) op << ", ui_three"; 864 op << ";\n"; 865 } 866 867 if (writeAccess == INDEXACCESS_DYNAMIC_LOOP || readAccess == INDEXACCESS_DYNAMIC_LOOP) 868 op << "uniform mediump int " << matSizeName << ";\n"; 869 870 vtx << "\n"; 871 vtx << "void main()\n"; 872 vtx << "{\n"; 873 vtx << " gl_Position = a_position;\n"; 874 875 frag << "\n"; 876 frag << "void main()\n"; 877 frag << "{\n"; 878 879 // Write matrix. 880 if (isVertexCase) 881 op << " ${PRECISION} vec4 coords = a_coords;\n"; 882 else 883 op << " ${PRECISION} vec4 coords = v_coords;\n"; 884 885 op << " ${PRECISION} ${MAT_TYPE} tmp;\n"; 886 if (writeAccess == INDEXACCESS_STATIC) 887 { 888 op << " tmp[0] = ${VEC_TYPE}(coords);\n"; 889 if (matSize >= 2) op << " tmp[1] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n"; 890 if (matSize >= 3) op << " tmp[2] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n"; 891 if (matSize >= 4) op << " tmp[3] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n"; 892 } 893 else if (writeAccess == INDEXACCESS_DYNAMIC) 894 { 895 op << " tmp[ui_zero] = ${VEC_TYPE}(coords);\n"; 896 if (matSize >= 2) op << " tmp[ui_one] = ${VEC_TYPE}(coords.yzwx) * 0.5;\n"; 897 if (matSize >= 3) op << " tmp[ui_two] = ${VEC_TYPE}(coords.zwxy) * 0.25;\n"; 898 if (matSize >= 4) op << " tmp[ui_three] = ${VEC_TYPE}(coords.wxyz) * 0.125;\n"; 899 } 900 else if (writeAccess == INDEXACCESS_STATIC_LOOP) 901 { 902 op << " for (int i = 0; i < " << matSize << "; i++)\n"; 903 op << " {\n"; 904 op << " tmp[i] = ${VEC_TYPE}(coords);\n"; 905 op << " coords = coords.yzwx * 0.5;\n"; 906 op << " }\n"; 907 } 908 else 909 { 910 DE_ASSERT(writeAccess == INDEXACCESS_DYNAMIC_LOOP); 911 op << " for (int i = 0; i < " << matSizeName << "; i++)\n"; 912 op << " {\n"; 913 op << " tmp[i] = ${VEC_TYPE}(coords);\n"; 914 op << " coords = coords.yzwx * 0.5;\n"; 915 op << " }\n"; 916 } 917 918 // Read matrix. 919 op << " ${PRECISION} ${VEC_TYPE} res = ${VEC_TYPE}(0.0);\n"; 920 if (readAccess == INDEXACCESS_STATIC) 921 { 922 op << " res += tmp[0];\n"; 923 if (matSize >= 2) op << " res += tmp[1];\n"; 924 if (matSize >= 3) op << " res += tmp[2];\n"; 925 if (matSize >= 4) op << " res += tmp[3];\n"; 926 } 927 else if (readAccess == INDEXACCESS_DYNAMIC) 928 { 929 op << " res += tmp[ui_zero];\n"; 930 if (matSize >= 2) op << " res += tmp[ui_one];\n"; 931 if (matSize >= 3) op << " res += tmp[ui_two];\n"; 932 if (matSize >= 4) op << " res += tmp[ui_three];\n"; 933 } 934 else if (readAccess == INDEXACCESS_STATIC_LOOP) 935 { 936 op << " for (int i = 0; i < " << matSize << "; i++)\n"; 937 op << " res += tmp[i];\n"; 938 } 939 else 940 { 941 DE_ASSERT(readAccess == INDEXACCESS_DYNAMIC_LOOP); 942 op << " for (int i = 0; i < " << matSizeName << "; i++)\n"; 943 op << " res += tmp[i];\n"; 944 } 945 946 if (isVertexCase) 947 { 948 vtx << " v_color = vec4(res${PADDING});\n"; 949 frag << " gl_FragColor = v_color;\n"; 950 } 951 else 952 { 953 vtx << " v_coords = a_coords;\n"; 954 frag << " gl_FragColor = vec4(res${PADDING});\n"; 955 } 956 957 vtx << "}\n"; 958 frag << "}\n"; 959 960 // Fill in shader templates. 961 map<string, string> params; 962 params.insert(pair<string, string>("MAT_TYPE", getDataTypeName(varType))); 963 params.insert(pair<string, string>("VEC_TYPE", getDataTypeName(vecType))); 964 params.insert(pair<string, string>("PRECISION", "mediump")); 965 966 if (matSize == 2) 967 params.insert(pair<string, string>("PADDING", ", 0.0, 1.0")); 968 else if (matSize == 3) 969 params.insert(pair<string, string>("PADDING", ", 1.0")); 970 else 971 params.insert(pair<string, string>("PADDING", "")); 972 973 StringTemplate vertTemplate(vtx.str().c_str()); 974 StringTemplate fragTemplate(frag.str().c_str()); 975 string vertexShaderSource = vertTemplate.specialize(params); 976 string fragmentShaderSource = fragTemplate.specialize(params); 977 978 ShaderEvalFunc evalFunc = getMatrixSubscriptEvalFunc(varType); 979 deUint32 requirements = 0; 980 981 if (readAccess == INDEXACCESS_DYNAMIC || writeAccess == INDEXACCESS_DYNAMIC) 982 requirements |= REQUIREMENT_UNIFORM_INDEXING; 983 984 if (readAccess == INDEXACCESS_DYNAMIC_LOOP || writeAccess == INDEXACCESS_DYNAMIC_LOOP) 985 requirements |= (isVertexCase ? REQUIREMENT_VERTEX_UNIFORM_LOOPS : REQUIREMENT_FRAGMENT_UNIFORM_LOOPS) | REQUIREMENT_UNIFORM_INDEXING; 986 987 return new ShaderIndexingCase(context, caseName, description, isVertexCase, varType, evalFunc, requirements, vertexShaderSource.c_str(), fragmentShaderSource.c_str()); 988 } 989 990 // ShaderIndexingTests. 991 992 ShaderIndexingTests::ShaderIndexingTests(Context& context) 993 : TestCaseGroup(context, "indexing", "Indexing Tests") 994 { 995 } 996 997 ShaderIndexingTests::~ShaderIndexingTests (void) 998 { 999 } 1000 1001 void ShaderIndexingTests::init (void) 1002 { 1003 static const ShaderType s_shaderTypes[] = 1004 { 1005 SHADERTYPE_VERTEX, 1006 SHADERTYPE_FRAGMENT 1007 }; 1008 1009 static const DataType s_floatAndVecTypes[] = 1010 { 1011 TYPE_FLOAT, 1012 TYPE_FLOAT_VEC2, 1013 TYPE_FLOAT_VEC3, 1014 TYPE_FLOAT_VEC4 1015 }; 1016 1017 // Varying array access cases. 1018 { 1019 TestCaseGroup* varyingGroup = new TestCaseGroup(m_context, "varying_array", "Varying array access tests."); 1020 addChild(varyingGroup); 1021 1022 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++) 1023 { 1024 DataType varType = s_floatAndVecTypes[typeNdx]; 1025 for (int vertAccess = 0; vertAccess < INDEXACCESS_LAST; vertAccess++) 1026 { 1027 for (int fragAccess = 0; fragAccess < INDEXACCESS_LAST; fragAccess++) 1028 { 1029 const char* vertAccessName = getIndexAccessTypeName((IndexAccessType)vertAccess); 1030 const char* fragAccessName = getIndexAccessTypeName((IndexAccessType)fragAccess); 1031 string name = string(getDataTypeName(varType)) + "_" + vertAccessName + "_write_" + fragAccessName + "_read"; 1032 string desc = string("Varying array with ") + vertAccessName + " write in vertex shader and " + fragAccessName + " read in fragment shader."; 1033 varyingGroup->addChild(createVaryingArrayCase(m_context, name.c_str(), desc.c_str(), varType, (IndexAccessType)vertAccess, (IndexAccessType)fragAccess)); 1034 } 1035 } 1036 } 1037 } 1038 1039 // Uniform array access cases. 1040 { 1041 TestCaseGroup* uniformGroup = new TestCaseGroup(m_context, "uniform_array", "Uniform array access tests."); 1042 addChild(uniformGroup); 1043 1044 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++) 1045 { 1046 DataType varType = s_floatAndVecTypes[typeNdx]; 1047 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++) 1048 { 1049 const char* readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess); 1050 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++) 1051 { 1052 ShaderType shaderType = s_shaderTypes[shaderTypeNdx]; 1053 const char* shaderTypeName = getShaderTypeName(shaderType); 1054 string name = string(getDataTypeName(varType)) + "_" + readAccessName + "_read_" + shaderTypeName; 1055 string desc = string("Uniform array with ") + readAccessName + " read in " + shaderTypeName + " shader."; 1056 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX); 1057 uniformGroup->addChild(createUniformArrayCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (IndexAccessType)readAccess)); 1058 } 1059 } 1060 } 1061 } 1062 1063 // Temporary array access cases. 1064 { 1065 TestCaseGroup* tmpGroup = new TestCaseGroup(m_context, "tmp_array", "Temporary array access tests."); 1066 addChild(tmpGroup); 1067 1068 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_floatAndVecTypes); typeNdx++) 1069 { 1070 DataType varType = s_floatAndVecTypes[typeNdx]; 1071 for (int writeAccess = 0; writeAccess < INDEXACCESS_LAST; writeAccess++) 1072 { 1073 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++) 1074 { 1075 const char* writeAccessName = getIndexAccessTypeName((IndexAccessType)writeAccess); 1076 const char* readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess); 1077 1078 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++) 1079 { 1080 ShaderType shaderType = s_shaderTypes[shaderTypeNdx]; 1081 const char* shaderTypeName = getShaderTypeName(shaderType); 1082 string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; 1083 string desc = string("Temporary array with ") + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; 1084 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX); 1085 tmpGroup->addChild(createTmpArrayCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (IndexAccessType)writeAccess, (IndexAccessType)readAccess)); 1086 } 1087 } 1088 } 1089 } 1090 } 1091 1092 // Vector indexing with subscripts. 1093 { 1094 TestCaseGroup* vecGroup = new TestCaseGroup(m_context, "vector_subscript", "Vector subscript indexing."); 1095 addChild(vecGroup); 1096 1097 static const DataType s_vectorTypes[] = 1098 { 1099 TYPE_FLOAT_VEC2, 1100 TYPE_FLOAT_VEC3, 1101 TYPE_FLOAT_VEC4 1102 }; 1103 1104 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_vectorTypes); typeNdx++) 1105 { 1106 DataType varType = s_vectorTypes[typeNdx]; 1107 for (int writeAccess = 0; writeAccess < VECTORACCESS_LAST; writeAccess++) 1108 { 1109 for (int readAccess = 0; readAccess < VECTORACCESS_LAST; readAccess++) 1110 { 1111 const char* writeAccessName = getVectorAccessTypeName((VectorAccessType)writeAccess); 1112 const char* readAccessName = getVectorAccessTypeName((VectorAccessType)readAccess); 1113 1114 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++) 1115 { 1116 ShaderType shaderType = s_shaderTypes[shaderTypeNdx]; 1117 const char* shaderTypeName = getShaderTypeName(shaderType); 1118 string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; 1119 string desc = string("Vector subscript access with ") + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; 1120 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX); 1121 vecGroup->addChild(createVectorSubscriptCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (VectorAccessType)writeAccess, (VectorAccessType)readAccess)); 1122 } 1123 } 1124 } 1125 } 1126 } 1127 1128 // Matrix indexing with subscripts. 1129 { 1130 TestCaseGroup* matGroup = new TestCaseGroup(m_context, "matrix_subscript", "Matrix subscript indexing."); 1131 addChild(matGroup); 1132 1133 static const DataType s_matrixTypes[] = 1134 { 1135 TYPE_FLOAT_MAT2, 1136 TYPE_FLOAT_MAT3, 1137 TYPE_FLOAT_MAT4 1138 }; 1139 1140 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(s_matrixTypes); typeNdx++) 1141 { 1142 DataType varType = s_matrixTypes[typeNdx]; 1143 for (int writeAccess = 0; writeAccess < INDEXACCESS_LAST; writeAccess++) 1144 { 1145 for (int readAccess = 0; readAccess < INDEXACCESS_LAST; readAccess++) 1146 { 1147 const char* writeAccessName = getIndexAccessTypeName((IndexAccessType)writeAccess); 1148 const char* readAccessName = getIndexAccessTypeName((IndexAccessType)readAccess); 1149 1150 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(s_shaderTypes); shaderTypeNdx++) 1151 { 1152 ShaderType shaderType = s_shaderTypes[shaderTypeNdx]; 1153 const char* shaderTypeName = getShaderTypeName(shaderType); 1154 string name = string(getDataTypeName(varType)) + "_" + writeAccessName + "_write_" + readAccessName + "_read_" + shaderTypeName; 1155 string desc = string("Vector subscript access with ") + writeAccessName + " write and " + readAccessName + " read in " + shaderTypeName + " shader."; 1156 bool isVertexCase = ((ShaderType)shaderType == SHADERTYPE_VERTEX); 1157 matGroup->addChild(createMatrixSubscriptCase(m_context, name.c_str(), desc.c_str(), isVertexCase, varType, (IndexAccessType)writeAccess, (IndexAccessType)readAccess)); 1158 } 1159 } 1160 } 1161 } 1162 } 1163 } 1164 1165 } // Functional 1166 } // gles2 1167 } // deqp 1168