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