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