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