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