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 struct tests. 24 *//*--------------------------------------------------------------------*/ 25 26 #include "vktShaderRenderStructTests.hpp" 27 #include "vktShaderRender.hpp" 28 #include "tcuStringTemplate.hpp" 29 #include "deMath.h" 30 31 namespace vkt 32 { 33 namespace sr 34 { 35 namespace 36 { 37 38 class ShaderStructCase : public ShaderRenderCase 39 { 40 public: 41 ShaderStructCase (tcu::TestContext& testCtx, 42 const std::string& name, 43 const std::string& description, 44 bool isVertexCase, 45 ShaderEvalFunc evalFunc, 46 UniformSetupFunc setupUniformsFunc, 47 const std::string& vertShaderSource, 48 const std::string& fragShaderSource); 49 ~ShaderStructCase (void); 50 51 private: 52 ShaderStructCase (const ShaderStructCase&); 53 ShaderStructCase& operator= (const ShaderStructCase&); 54 }; 55 56 ShaderStructCase::ShaderStructCase (tcu::TestContext& testCtx, 57 const std::string& name, 58 const std::string& description, 59 bool isVertexCase, 60 ShaderEvalFunc evalFunc, 61 UniformSetupFunc setupUniformsFunc, 62 const std::string& vertShaderSource, 63 const std::string& fragShaderSource) 64 : ShaderRenderCase (testCtx, name, description, isVertexCase, evalFunc, new UniformSetup(setupUniformsFunc), DE_NULL) 65 { 66 m_vertShaderSource = vertShaderSource; 67 m_fragShaderSource = fragShaderSource; 68 } 69 70 ShaderStructCase::~ShaderStructCase (void) 71 { 72 } 73 74 static de::MovePtr<ShaderStructCase> createStructCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool isVertexCase, ShaderEvalFunc evalFunc, UniformSetupFunc uniformFunc, const LineStream& shaderSrc) 75 { 76 static std::string defaultVertSrc = 77 "#version 310 es\n" 78 "layout(location = 0) in highp vec4 a_position;\n" 79 "layout(location = 1) in highp vec4 a_coords;\n" 80 "layout(location = 0) out mediump vec4 v_coords;\n\n" 81 "void main (void)\n" 82 "{\n" 83 " v_coords = a_coords;\n" 84 " gl_Position = a_position;\n" 85 "}\n"; 86 static std::string defaultFragSrc = 87 "#version 310 es\n" 88 "layout(location = 0) in mediump vec4 v_color;\n" 89 "layout(location = 0) out mediump vec4 o_color;\n\n" 90 "void main (void)\n" 91 "{\n" 92 " o_color = v_color;\n" 93 "}\n"; 94 95 // Fill in specialization parameters and build the shader source. 96 std::string vertSrc; 97 std::string fragSrc; 98 std::map<std::string, std::string> spParams; 99 100 if (isVertexCase) 101 { 102 spParams["HEADER"] = 103 "#version 310 es\n" 104 "layout(location = 0) in highp vec4 a_position;\n" 105 "layout(location = 1) in highp vec4 a_coords;\n" 106 "layout(location = 0) out mediump vec4 v_color;"; 107 spParams["COORDS"] = "a_coords"; 108 spParams["DST"] = "v_color"; 109 spParams["ASSIGN_POS"] = "gl_Position = a_position;"; 110 111 vertSrc = tcu::StringTemplate(shaderSrc.str()).specialize(spParams); 112 fragSrc = defaultFragSrc; 113 } 114 else 115 { 116 spParams["HEADER"] = 117 "#version 310 es\n" 118 "layout(location = 0) in mediump vec4 v_coords;\n" 119 "layout(location = 0) out mediump vec4 o_color;"; 120 spParams["COORDS"] = "v_coords"; 121 spParams["DST"] = "o_color"; 122 spParams["ASSIGN_POS"] = ""; 123 124 vertSrc = defaultVertSrc; 125 fragSrc = tcu::StringTemplate(shaderSrc.str()).specialize(spParams); 126 } 127 128 return de::MovePtr<ShaderStructCase>(new ShaderStructCase(testCtx, name, description, isVertexCase, evalFunc, uniformFunc, vertSrc, fragSrc)); 129 } 130 131 class LocalStructTests : public tcu::TestCaseGroup 132 { 133 public: 134 LocalStructTests (tcu::TestContext& testCtx) 135 : TestCaseGroup(testCtx, "local", "Local structs") 136 { 137 } 138 139 ~LocalStructTests (void) 140 { 141 } 142 143 virtual void init (void); 144 }; 145 146 void LocalStructTests::init (void) 147 { 148 #define LOCAL_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \ 149 do { \ 150 struct SetUniforms_##NAME { static void setUniforms (ShaderRenderCaseInstance& instance, const tcu::Vec4&) SET_UNIFORMS_BODY }; \ 151 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; \ 152 addChild(createStructCase(m_testCtx, #NAME "_vertex", DESCRIPTION, true, &Eval_##NAME::eval, &SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \ 153 addChild(createStructCase(m_testCtx, #NAME "_fragment", DESCRIPTION, false, &Eval_##NAME::eval, &SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \ 154 } while (deGetFalse()) 155 156 LOCAL_STRUCT_CASE(basic, "Basic struct usage", 157 LineStream() 158 << "${HEADER}" 159 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 160 << "" 161 << "struct S {" 162 << " mediump float a;" 163 << " mediump vec3 b;" 164 << " int c;" 165 << "};" 166 << "" 167 << "void main (void)" 168 << "{" 169 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" 170 << " s.b = ${COORDS}.yzw;" 171 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 172 << " ${ASSIGN_POS}" 173 << "}", 174 { 175 instance.useUniform(0u, UI_ONE); 176 }, 177 { 178 c.color.xyz() = c.coords.swizzle(0, 1, 2); 179 }); 180 181 LOCAL_STRUCT_CASE(nested, "Nested struct", 182 LineStream() 183 << "${HEADER}" 184 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 185 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 186 << "" 187 << "struct T {" 188 << " int a;" 189 << " mediump vec2 b;" 190 << "};" 191 << "struct S {" 192 << " mediump float a;" 193 << " T b;" 194 << " int c;" 195 << "};" 196 << "" 197 << "void main (void)" 198 << "{" 199 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" 200 << " s.b = T(ui_zero, ${COORDS}.yz);" 201 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 202 << " ${ASSIGN_POS}" 203 << "}", 204 { 205 instance.useUniform(0u, UI_ZERO); 206 instance.useUniform(1u, UI_ONE); 207 }, 208 { 209 c.color.xyz() = c.coords.swizzle(0, 1, 2); 210 }); 211 212 LOCAL_STRUCT_CASE(array_member, "Struct with array member", 213 LineStream() 214 << "${HEADER}" 215 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 216 << "" 217 << "struct S {" 218 << " mediump float a;" 219 << " mediump float b[3];" 220 << " int c;" 221 << "};" 222 << "" 223 << "void main (void)" 224 << "{" 225 << " S s;" 226 << " s.a = ${COORDS}.w;" 227 << " s.c = ui_one;" 228 << " s.b[0] = ${COORDS}.z;" 229 << " s.b[1] = ${COORDS}.y;" 230 << " s.b[2] = ${COORDS}.x;" 231 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" 232 << " ${ASSIGN_POS}" 233 << "}", 234 { 235 instance.useUniform(0u, UI_ONE); 236 }, 237 { 238 c.color.xyz() = c.coords.swizzle(3, 2, 1); 239 }); 240 241 LOCAL_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", 242 LineStream() 243 << "${HEADER}" 244 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 245 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 246 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 247 << "" 248 << "struct S {" 249 << " mediump float a;" 250 << " mediump float b[3];" 251 << " int c;" 252 << "};" 253 << "" 254 << "void main (void)" 255 << "{" 256 << " S s;" 257 << " s.a = ${COORDS}.w;" 258 << " s.c = ui_one;" 259 << " s.b[0] = ${COORDS}.z;" 260 << " s.b[1] = ${COORDS}.y;" 261 << " s.b[2] = ${COORDS}.x;" 262 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" 263 << " ${ASSIGN_POS}" 264 << "}", 265 { 266 instance.useUniform(0u, UI_ZERO); 267 instance.useUniform(1u, UI_ONE); 268 instance.useUniform(2u, UI_TWO); 269 }, 270 { 271 c.color.xyz() = c.coords.swizzle(1,2,0); 272 }); 273 274 LOCAL_STRUCT_CASE(struct_array, "Struct array", 275 LineStream() 276 << "${HEADER}" 277 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 278 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 279 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 280 << "" 281 << "struct S {" 282 << " mediump float a;" 283 << " mediump int b;" 284 << "};" 285 << "" 286 << "void main (void)" 287 << "{" 288 << " S s[3];" 289 << " s[0] = S(${COORDS}.x, ui_zero);" 290 << " s[1].a = ${COORDS}.y;" 291 << " s[1].b = ui_one;" 292 << " s[2] = S(${COORDS}.z, ui_two);" 293 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" 294 << " ${ASSIGN_POS}" 295 << "}", 296 { 297 instance.useUniform(0u, UI_ZERO); 298 instance.useUniform(1u, UI_ONE); 299 instance.useUniform(2u, UI_TWO); 300 }, 301 { 302 c.color.xyz() = c.coords.swizzle(2, 1, 0); 303 }); 304 305 LOCAL_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", 306 LineStream() 307 << "${HEADER}" 308 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 309 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 310 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 311 << "" 312 << "struct S {" 313 << " mediump float a;" 314 << " mediump int b;" 315 << "};" 316 << "" 317 << "void main (void)" 318 << "{" 319 << " S s[3];" 320 << " s[0] = S(${COORDS}.x, ui_zero);" 321 << " s[1].a = ${COORDS}.y;" 322 << " s[1].b = ui_one;" 323 << " s[2] = S(${COORDS}.z, ui_two);" 324 << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);" 325 << " ${ASSIGN_POS}" 326 << "}", 327 { 328 instance.useUniform(0u, UI_ZERO); 329 instance.useUniform(1u, UI_ONE); 330 instance.useUniform(2u, UI_TWO); 331 }, 332 { 333 c.color.xyz() = c.coords.swizzle(2, 1, 0); 334 }); 335 336 LOCAL_STRUCT_CASE(nested_struct_array, "Nested struct array", 337 LineStream() 338 << "${HEADER}" 339 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 340 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 341 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 342 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };" 343 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };" 344 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };" 345 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };" 346 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };" 347 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };" 348 << "" 349 << "struct T {" 350 << " mediump float a;" 351 << " mediump vec2 b[2];" 352 << "};" 353 << "struct S {" 354 << " mediump float a;" 355 << " T b[3];" 356 << " int c;" 357 << "};" 358 << "" 359 << "void main (void)" 360 << "{" 361 << " S s[2];" 362 << "" 363 << " // S[0]" 364 << " s[0].a = ${COORDS}.x;" 365 << " s[0].b[0].a = uf_half;" 366 << " s[0].b[0].b[0] = ${COORDS}.xy;" 367 << " s[0].b[0].b[1] = ${COORDS}.zw;" 368 << " s[0].b[1].a = uf_third;" 369 << " s[0].b[1].b[0] = ${COORDS}.zw;" 370 << " s[0].b[1].b[1] = ${COORDS}.xy;" 371 << " s[0].b[2].a = uf_fourth;" 372 << " s[0].b[2].b[0] = ${COORDS}.xz;" 373 << " s[0].b[2].b[1] = ${COORDS}.yw;" 374 << " s[0].c = ui_zero;" 375 << "" 376 << " // S[1]" 377 << " s[1].a = ${COORDS}.w;" 378 << " s[1].b[0].a = uf_two;" 379 << " s[1].b[0].b[0] = ${COORDS}.xx;" 380 << " s[1].b[0].b[1] = ${COORDS}.yy;" 381 << " s[1].b[1].a = uf_three;" 382 << " s[1].b[1].b[0] = ${COORDS}.zz;" 383 << " s[1].b[1].b[1] = ${COORDS}.ww;" 384 << " s[1].b[2].a = uf_four;" 385 << " s[1].b[2].b[0] = ${COORDS}.yx;" 386 << " s[1].b[2].b[1] = ${COORDS}.wz;" 387 << " s[1].c = ui_one;" 388 << "" 389 << " mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5" 390 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" 391 << " mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w + w) * 0.333" 392 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" 393 << " ${DST} = vec4(r, g, b, a);" 394 << " ${ASSIGN_POS}" 395 << "}", 396 { 397 instance.useUniform(0u, UI_ZERO); 398 instance.useUniform(1u, UI_ONE); 399 instance.useUniform(2u, UI_TWO); 400 instance.useUniform(3u, UF_TWO); 401 instance.useUniform(4u, UF_THREE); 402 instance.useUniform(5u, UF_FOUR); 403 instance.useUniform(6u, UF_HALF); 404 instance.useUniform(7u, UF_THIRD); 405 instance.useUniform(8u, UF_FOURTH); 406 }, 407 { 408 c.color.xyz() = c.coords.swizzle(2, 0, 3); 409 }); 410 411 LOCAL_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", 412 LineStream() 413 << "${HEADER}" 414 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 415 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 416 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 417 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };" 418 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };" 419 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };" 420 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };" 421 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };" 422 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };" 423 << "" 424 << "struct T {" 425 << " mediump float a;" 426 << " mediump vec2 b[2];" 427 << "};" 428 << "struct S {" 429 << " mediump float a;" 430 << " T b[3];" 431 << " int c;" 432 << "};" 433 << "" 434 << "void main (void)" 435 << "{" 436 << " S s[2];" 437 << "" 438 << " // S[0]" 439 << " s[0].a = ${COORDS}.x;" 440 << " s[0].b[0].a = uf_half;" 441 << " s[0].b[0].b[0] = ${COORDS}.xy;" 442 << " s[0].b[0].b[1] = ${COORDS}.zw;" 443 << " s[0].b[1].a = uf_third;" 444 << " s[0].b[1].b[0] = ${COORDS}.zw;" 445 << " s[0].b[1].b[1] = ${COORDS}.xy;" 446 << " s[0].b[2].a = uf_fourth;" 447 << " s[0].b[2].b[0] = ${COORDS}.xz;" 448 << " s[0].b[2].b[1] = ${COORDS}.yw;" 449 << " s[0].c = ui_zero;" 450 << "" 451 << " // S[1]" 452 << " s[1].a = ${COORDS}.w;" 453 << " s[1].b[0].a = uf_two;" 454 << " s[1].b[0].b[0] = ${COORDS}.xx;" 455 << " s[1].b[0].b[1] = ${COORDS}.yy;" 456 << " s[1].b[1].a = uf_three;" 457 << " s[1].b[1].b[0] = ${COORDS}.zz;" 458 << " s[1].b[1].b[1] = ${COORDS}.ww;" 459 << " s[1].b[2].a = uf_four;" 460 << " s[1].b[2].b[0] = ${COORDS}.yx;" 461 << " s[1].b[2].b[1] = ${COORDS}.wz;" 462 << " s[1].c = ui_one;" 463 << "" 464 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5" 465 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * s[ui_one].b[2].a; // x * 0.25 * 4" 466 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333" 467 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0" 468 << " ${DST} = vec4(r, g, b, a);" 469 << " ${ASSIGN_POS}" 470 << "}", 471 { 472 instance.useUniform(0u, UI_ZERO); 473 instance.useUniform(1u, UI_ONE); 474 instance.useUniform(2u, UI_TWO); 475 instance.useUniform(3u, UF_TWO); 476 instance.useUniform(4u, UF_THREE); 477 instance.useUniform(5u, UF_FOUR); 478 instance.useUniform(6u, UF_HALF); 479 instance.useUniform(7u, UF_THIRD); 480 instance.useUniform(8u, UF_FOURTH); 481 }, 482 { 483 c.color.xyz() = c.coords.swizzle(2, 0, 3); 484 }); 485 486 LOCAL_STRUCT_CASE(parameter, "Struct as a function parameter", 487 LineStream() 488 << "${HEADER}" 489 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 490 << "" 491 << "struct S {" 492 << " mediump float a;" 493 << " mediump vec3 b;" 494 << " int c;" 495 << "};" 496 << "" 497 << "mediump vec4 myFunc (S s)" 498 << "{" 499 << " return vec4(s.a, s.b.x, s.b.y, s.c);" 500 << "}" 501 << "" 502 << "void main (void)" 503 << "{" 504 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" 505 << " s.b = ${COORDS}.yzw;" 506 << " ${DST} = myFunc(s);" 507 << " ${ASSIGN_POS}" 508 << "}", 509 { 510 instance.useUniform(0u, UI_ONE); 511 }, 512 { 513 c.color.xyz() = c.coords.swizzle(0, 1, 2); 514 }); 515 516 LOCAL_STRUCT_CASE(parameter_nested, "Nested struct as a function parameter", 517 LineStream() 518 << "${HEADER}" 519 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 520 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 521 << "" 522 << "struct T {" 523 << " int a;" 524 << " mediump vec2 b;" 525 << "};" 526 << "struct S {" 527 << " mediump float a;" 528 << " T b;" 529 << " int c;" 530 << "};" 531 << "" 532 << "mediump vec4 myFunc (S s)" 533 << "{" 534 << " return vec4(s.a, s.b.b, s.b.a + s.c);" 535 << "}" 536 << "" 537 << "void main (void)" 538 << "{" 539 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" 540 << " s.b = T(ui_zero, ${COORDS}.yz);" 541 << " ${DST} = myFunc(s);" 542 << " ${ASSIGN_POS}" 543 << "}", 544 { 545 instance.useUniform(0u, UI_ZERO); 546 instance.useUniform(1u, UI_ONE); 547 }, 548 { 549 c.color.xyz() = c.coords.swizzle(0, 1, 2); 550 }); 551 552 LOCAL_STRUCT_CASE(return, "Struct as a return value", 553 LineStream() 554 << "${HEADER}" 555 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 556 << "" 557 << "struct S {" 558 << " mediump float a;" 559 << " mediump vec3 b;" 560 << " int c;" 561 << "};" 562 << "" 563 << "S myFunc (void)" 564 << "{" 565 << " S s = S(${COORDS}.x, vec3(0.0), ui_one);" 566 << " s.b = ${COORDS}.yzw;" 567 << " return s;" 568 << "}" 569 << "" 570 << "void main (void)" 571 << "{" 572 << " S s = myFunc();" 573 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 574 << " ${ASSIGN_POS}" 575 << "}", 576 { 577 instance.useUniform(0u, UI_ONE); 578 }, 579 { 580 c.color.xyz() = c.coords.swizzle(0, 1, 2); 581 }); 582 583 LOCAL_STRUCT_CASE(return_nested, "Nested struct", 584 LineStream() 585 << "${HEADER}" 586 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 587 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 588 << "" 589 << "struct T {" 590 << " int a;" 591 << " mediump vec2 b;" 592 << "};" 593 << "struct S {" 594 << " mediump float a;" 595 << " T b;" 596 << " int c;" 597 << "};" 598 << "" 599 << "S myFunc (void)" 600 << "{" 601 << " S s = S(${COORDS}.x, T(0, vec2(0.0)), ui_one);" 602 << " s.b = T(ui_zero, ${COORDS}.yz);" 603 << " return s;" 604 << "}" 605 << "" 606 << "void main (void)" 607 << "{" 608 << " S s = myFunc();" 609 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 610 << " ${ASSIGN_POS}" 611 << "}", 612 { 613 instance.useUniform(0u, UI_ZERO); 614 instance.useUniform(1u, UI_ONE); 615 }, 616 { 617 c.color.xyz() = c.coords.swizzle(0, 1, 2); 618 }); 619 620 LOCAL_STRUCT_CASE(conditional_assignment, "Conditional struct assignment", 621 LineStream() 622 << "${HEADER}" 623 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 624 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 625 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };" 626 << "" 627 << "struct S {" 628 << " mediump float a;" 629 << " mediump vec3 b;" 630 << " int c;" 631 << "};" 632 << "" 633 << "void main (void)" 634 << "{" 635 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" 636 << " if (uf_one > 0.0)" 637 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" 638 << " ${DST} = vec4(s.a, s.b.xy, s.c);" 639 << " ${ASSIGN_POS}" 640 << "}", 641 { 642 instance.useUniform(0u, UI_ZERO); 643 instance.useUniform(1u, UI_ONE); 644 instance.useUniform(2u, UF_ONE); 645 }, 646 { 647 c.color.xyz() = c.coords.swizzle(3, 2, 1); 648 }); 649 650 LOCAL_STRUCT_CASE(loop_assignment, "Struct assignment in loop", 651 LineStream() 652 << "${HEADER}" 653 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 654 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 655 << "" 656 << "struct S {" 657 << " mediump float a;" 658 << " mediump vec3 b;" 659 << " int c;" 660 << "};" 661 << "" 662 << "void main (void)" 663 << "{" 664 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" 665 << " for (int i = 0; i < 3; i++)" 666 << " {" 667 << " if (i == 1)" 668 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" 669 << " }" 670 << " ${DST} = vec4(s.a, s.b.xy, s.c);" 671 << " ${ASSIGN_POS}" 672 << "}", 673 { 674 instance.useUniform(0u, UI_ZERO); 675 instance.useUniform(1u, UI_ONE); 676 }, 677 { 678 c.color.xyz() = c.coords.swizzle(3, 2, 1); 679 }); 680 681 LOCAL_STRUCT_CASE(dynamic_loop_assignment, "Struct assignment in loop", 682 LineStream() 683 << "${HEADER}" 684 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 685 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 686 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_three; };" 687 << "" 688 << "struct S {" 689 << " mediump float a;" 690 << " mediump vec3 b;" 691 << " int c;" 692 << "};" 693 << "" 694 << "void main (void)" 695 << "{" 696 << " S s = S(${COORDS}.x, ${COORDS}.yzw, ui_zero);" 697 << " for (int i = 0; i < ui_three; i++)" 698 << " {" 699 << " if (i == ui_one)" 700 << " s = S(${COORDS}.w, ${COORDS}.zyx, ui_one);" 701 << " }" 702 << " ${DST} = vec4(s.a, s.b.xy, s.c);" 703 << " ${ASSIGN_POS}" 704 << "}", 705 { 706 instance.useUniform(0u, UI_ZERO); 707 instance.useUniform(1u, UI_ONE); 708 instance.useUniform(2u, UI_THREE); 709 }, 710 { 711 c.color.xyz() = c.coords.swizzle(3, 2, 1); 712 }); 713 714 LOCAL_STRUCT_CASE(nested_conditional_assignment, "Conditional assignment of nested struct", 715 LineStream() 716 << "${HEADER}" 717 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 718 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 719 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };" 720 << "" 721 << "struct T {" 722 << " int a;" 723 << " mediump vec2 b;" 724 << "};" 725 << "struct S {" 726 << " mediump float a;" 727 << " T b;" 728 << " int c;" 729 << "};" 730 << "" 731 << "void main (void)" 732 << "{" 733 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" 734 << " if (uf_one > 0.0)" 735 << " s.b = T(ui_zero, ${COORDS}.zw);" 736 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" 737 << " ${ASSIGN_POS}" 738 << "}", 739 { 740 instance.useUniform(0u, UI_ZERO); 741 instance.useUniform(1u, UI_ONE); 742 instance.useUniform(2u, UF_ONE); 743 }, 744 { 745 c.color.xyz() = c.coords.swizzle(0, 2, 3); 746 }); 747 748 LOCAL_STRUCT_CASE(nested_loop_assignment, "Nested struct assignment in loop", 749 LineStream() 750 << "${HEADER}" 751 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 752 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 753 << "layout (std140, set = 0, binding = 2) uniform buffer2 { mediump float uf_one; };" 754 << "" 755 << "struct T {" 756 << " int a;" 757 << " mediump vec2 b;" 758 << "};" 759 << "struct S {" 760 << " mediump float a;" 761 << " T b;" 762 << " int c;" 763 << "};" 764 << "" 765 << "void main (void)" 766 << "{" 767 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" 768 << " for (int i = 0; i < 3; i++)" 769 << " {" 770 << " if (i == 1)" 771 << " s.b = T(ui_zero, ${COORDS}.zw);" 772 << " }" 773 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" 774 << " ${ASSIGN_POS}" 775 << "}", 776 { 777 instance.useUniform(0u, UI_ZERO); 778 instance.useUniform(1u, UI_ONE); 779 instance.useUniform(2u, UF_ONE); 780 }, 781 { 782 c.color.xyz() = c.coords.swizzle(0, 2, 3); 783 }); 784 785 LOCAL_STRUCT_CASE(nested_dynamic_loop_assignment, "Nested struct assignment in dynamic loop", 786 LineStream() 787 << "${HEADER}" 788 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 789 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 790 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_three; };" 791 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_one; };" 792 << "" 793 << "struct T {" 794 << " int a;" 795 << " mediump vec2 b;" 796 << "};" 797 << "struct S {" 798 << " mediump float a;" 799 << " T b;" 800 << " int c;" 801 << "};" 802 << "" 803 << "void main (void)" 804 << "{" 805 << " S s = S(${COORDS}.x, T(ui_one, ${COORDS}.yz), ui_one);" 806 << " for (int i = 0; i < ui_three; i++)" 807 << " {" 808 << " if (i == ui_one)" 809 << " s.b = T(ui_zero, ${COORDS}.zw);" 810 << " }" 811 << " ${DST} = vec4(s.a, s.b.b, s.c - s.b.a);" 812 << " ${ASSIGN_POS}" 813 << "}", 814 { 815 instance.useUniform(0u, UI_ZERO); 816 instance.useUniform(1u, UI_ONE); 817 instance.useUniform(2u, UI_THREE); 818 instance.useUniform(3u, UF_ONE); 819 }, 820 { 821 c.color.xyz() = c.coords.swizzle(0, 2, 3); 822 }); 823 824 LOCAL_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 825 LineStream() 826 << "${HEADER}" 827 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 828 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 829 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 830 << "" 831 << "struct S {" 832 << " mediump float a;" 833 << " mediump int b;" 834 << "};" 835 << "" 836 << "void main (void)" 837 << "{" 838 << " S s[3];" 839 << " s[0] = S(${COORDS}.x, ui_zero);" 840 << " s[1].a = ${COORDS}.y;" 841 << " s[1].b = -ui_one;" 842 << " s[2] = S(${COORDS}.z, ui_two);" 843 << "" 844 << " mediump float rgb[3];" 845 << " int alpha = 0;" 846 << " for (int i = 0; i < 3; i++)" 847 << " {" 848 << " rgb[i] = s[2-i].a;" 849 << " alpha += s[i].b;" 850 << " }" 851 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 852 << " ${ASSIGN_POS}" 853 << "}", 854 { 855 instance.useUniform(0u, UI_ZERO); 856 instance.useUniform(1u, UI_ONE); 857 instance.useUniform(2u, UI_TWO); 858 }, 859 { 860 c.color.xyz() = c.coords.swizzle(2, 1, 0); 861 }); 862 863 LOCAL_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 864 LineStream() 865 << "${HEADER}" 866 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 867 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 868 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 869 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };" 870 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };" 871 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };" 872 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };" 873 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };" 874 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };" 875 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };" 876 << "" 877 << "struct T {" 878 << " mediump float a;" 879 << " mediump vec2 b[2];" 880 << "};" 881 << "struct S {" 882 << " mediump float a;" 883 << " T b[3];" 884 << " int c;" 885 << "};" 886 << "" 887 << "void main (void)" 888 << "{" 889 << " S s[2];" 890 << "" 891 << " // S[0]" 892 << " s[0].a = ${COORDS}.x;" 893 << " s[0].b[0].a = uf_half;" 894 << " s[0].b[0].b[0] = ${COORDS}.yx;" 895 << " s[0].b[0].b[1] = ${COORDS}.zx;" 896 << " s[0].b[1].a = uf_third;" 897 << " s[0].b[1].b[0] = ${COORDS}.yy;" 898 << " s[0].b[1].b[1] = ${COORDS}.wy;" 899 << " s[0].b[2].a = uf_fourth;" 900 << " s[0].b[2].b[0] = ${COORDS}.zx;" 901 << " s[0].b[2].b[1] = ${COORDS}.zy;" 902 << " s[0].c = ui_zero;" 903 << "" 904 << " // S[1]" 905 << " s[1].a = ${COORDS}.w;" 906 << " s[1].b[0].a = uf_two;" 907 << " s[1].b[0].b[0] = ${COORDS}.zx;" 908 << " s[1].b[0].b[1] = ${COORDS}.zy;" 909 << " s[1].b[1].a = uf_three;" 910 << " s[1].b[1].b[0] = ${COORDS}.zz;" 911 << " s[1].b[1].b[1] = ${COORDS}.ww;" 912 << " s[1].b[2].a = uf_four;" 913 << " s[1].b[2].b[0] = ${COORDS}.yx;" 914 << " s[1].b[2].b[1] = ${COORDS}.wz;" 915 << " s[1].c = ui_one;" 916 << "" 917 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 918 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 919 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 920 << " mediump float a = 1.0;" 921 << " for (int i = 0; i < 2; i++)" 922 << " {" 923 << " for (int j = 0; j < 3; j++)" 924 << " {" 925 << " r += s[0].b[j].b[i].y;" 926 << " g += s[i].b[j].b[0].x;" 927 << " b += s[i].b[j].b[1].x;" 928 << " a *= s[i].b[j].a;" 929 << " }" 930 << " }" 931 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 932 << " ${ASSIGN_POS}" 933 << "}", 934 { 935 instance.useUniform(0u, UI_ZERO); 936 instance.useUniform(1u, UI_ONE); 937 instance.useUniform(2u, UI_TWO); 938 instance.useUniform(3u, UF_TWO); 939 instance.useUniform(4u, UF_THREE); 940 instance.useUniform(5u, UF_FOUR); 941 instance.useUniform(6u, UF_HALF); 942 instance.useUniform(7u, UF_THIRD); 943 instance.useUniform(8u, UF_FOURTH); 944 instance.useUniform(9u, UF_SIXTH); 945 }, 946 { 947 c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; 948 }); 949 950 LOCAL_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", 951 LineStream() 952 << "${HEADER}" 953 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 954 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 955 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 956 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };" 957 << "" 958 << "struct S {" 959 << " mediump float a;" 960 << " mediump int b;" 961 << "};" 962 << "" 963 << "void main (void)" 964 << "{" 965 << " S s[3];" 966 << " s[0] = S(${COORDS}.x, ui_zero);" 967 << " s[1].a = ${COORDS}.y;" 968 << " s[1].b = -ui_one;" 969 << " s[2] = S(${COORDS}.z, ui_two);" 970 << "" 971 << " mediump float rgb[3];" 972 << " int alpha = 0;" 973 << " for (int i = 0; i < ui_three; i++)" 974 << " {" 975 << " rgb[i] = s[2-i].a;" 976 << " alpha += s[i].b;" 977 << " }" 978 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 979 << " ${ASSIGN_POS}" 980 << "}", 981 { 982 instance.useUniform(0u, UI_ZERO); 983 instance.useUniform(1u, UI_ONE); 984 instance.useUniform(2u, UI_TWO); 985 instance.useUniform(3u, UI_THREE); 986 }, 987 { 988 c.color.xyz() = c.coords.swizzle(2, 1, 0); 989 }); 990 991 LOCAL_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", 992 LineStream() 993 << "${HEADER}" 994 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 995 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 996 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 997 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };" 998 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };" 999 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };" 1000 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };" 1001 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };" 1002 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };" 1003 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };" 1004 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };" 1005 << "" 1006 << "struct T {" 1007 << " mediump float a;" 1008 << " mediump vec2 b[2];" 1009 << "};" 1010 << "struct S {" 1011 << " mediump float a;" 1012 << " T b[3];" 1013 << " int c;" 1014 << "};" 1015 << "" 1016 << "void main (void)" 1017 << "{" 1018 << " S s[2];" 1019 << "" 1020 << " s[0].a = ${COORDS}.x;" 1021 << " s[0].b[0].a = uf_half;" 1022 << " s[0].b[0].b[0] = ${COORDS}.yx;" 1023 << " s[0].b[0].b[1] = ${COORDS}.zx;" 1024 << " s[0].b[1].a = uf_third;" 1025 << " s[0].b[1].b[0] = ${COORDS}.yy;" 1026 << " s[0].b[1].b[1] = ${COORDS}.wy;" 1027 << " s[0].b[2].a = uf_fourth;" 1028 << " s[0].b[2].b[0] = ${COORDS}.zx;" 1029 << " s[0].b[2].b[1] = ${COORDS}.zy;" 1030 << " s[0].c = ui_zero;" 1031 << "" 1032 << " s[1].a = ${COORDS}.w;" 1033 << " s[1].b[0].a = uf_two;" 1034 << " s[1].b[0].b[0] = ${COORDS}.zx;" 1035 << " s[1].b[0].b[1] = ${COORDS}.zy;" 1036 << " s[1].b[1].a = uf_three;" 1037 << " s[1].b[1].b[0] = ${COORDS}.zz;" 1038 << " s[1].b[1].b[1] = ${COORDS}.ww;" 1039 << " s[1].b[2].a = uf_four;" 1040 << " s[1].b[2].b[0] = ${COORDS}.yx;" 1041 << " s[1].b[2].b[1] = ${COORDS}.wz;" 1042 << " s[1].c = ui_one;" 1043 << "" 1044 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1045 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1046 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1047 << " mediump float a = 1.0;" 1048 << " for (int i = 0; i < ui_two; i++)" 1049 << " {" 1050 << " for (int j = 0; j < ui_three; j++)" 1051 << " {" 1052 << " r += s[0].b[j].b[i].y;" 1053 << " g += s[i].b[j].b[0].x;" 1054 << " b += s[i].b[j].b[1].x;" 1055 << " a *= s[i].b[j].a;" 1056 << " }" 1057 << " }" 1058 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1059 << " ${ASSIGN_POS}" 1060 << "}", 1061 { 1062 instance.useUniform(0u, UI_ZERO); 1063 instance.useUniform(1u, UI_ONE); 1064 instance.useUniform(2u, UI_TWO); 1065 instance.useUniform(3u, UI_THREE); 1066 instance.useUniform(4u, UF_TWO); 1067 instance.useUniform(5u, UF_THREE); 1068 instance.useUniform(6u, UF_FOUR); 1069 instance.useUniform(7u, UF_HALF); 1070 instance.useUniform(8u, UF_THIRD); 1071 instance.useUniform(9u, UF_FOURTH); 1072 instance.useUniform(10u, UF_SIXTH); 1073 }, 1074 { 1075 c.color.xyz() = (c.coords.swizzle(0, 1, 2) + c.coords.swizzle(1, 2, 3)) * 0.5f; 1076 }); 1077 1078 LOCAL_STRUCT_CASE(basic_equal, "Basic struct equality", 1079 LineStream() 1080 << "${HEADER}" 1081 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1082 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 1083 << "" 1084 << "struct S {" 1085 << " mediump float a;" 1086 << " mediump vec3 b;" 1087 << " int c;" 1088 << "};" 1089 << "" 1090 << "void main (void)" 1091 << "{" 1092 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);" 1093 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);" 1094 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);" 1095 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);" 1096 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 1097 << " if (a == b) ${DST}.x = 1.0;" 1098 << " if (a == c) ${DST}.y = 1.0;" 1099 << " if (a == d) ${DST}.z = 1.0;" 1100 << " ${ASSIGN_POS}" 1101 << "}", 1102 { 1103 instance.useUniform(0u, UI_ONE); 1104 instance.useUniform(1u, UI_TWO); 1105 }, 1106 { 1107 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f)) 1108 c.color.x() = 1.0f; 1109 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f)) 1110 c.color.y() = 1.0f; 1111 }); 1112 1113 LOCAL_STRUCT_CASE(basic_not_equal, "Basic struct equality", 1114 LineStream() 1115 << "${HEADER}" 1116 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1117 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 1118 << "" 1119 << "struct S {" 1120 << " mediump float a;" 1121 << " mediump vec3 b;" 1122 << " int c;" 1123 << "};" 1124 << "" 1125 << "void main (void)" 1126 << "{" 1127 << " S a = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);" 1128 << " S b = S(floor(${COORDS}.x+0.5), vec3(0.0, floor(${COORDS}.y), 2.3), ui_one);" 1129 << " S c = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one);" 1130 << " S d = S(floor(${COORDS}.x), vec3(0.0, floor(${COORDS}.y), 2.3), ui_two);" 1131 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 1132 << " if (a != b) ${DST}.x = 1.0;" 1133 << " if (a != c) ${DST}.y = 1.0;" 1134 << " if (a != d) ${DST}.z = 1.0;" 1135 << " ${ASSIGN_POS}" 1136 << "}", 1137 { 1138 instance.useUniform(0u, UI_ONE); 1139 instance.useUniform(1u, UI_TWO); 1140 }, 1141 { 1142 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f)) 1143 c.color.x() = 1.0f; 1144 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f)) 1145 c.color.y() = 1.0f; 1146 c.color.z() = 1.0f; 1147 }); 1148 1149 LOCAL_STRUCT_CASE(nested_equal, "Nested struct struct equality", 1150 LineStream() 1151 << "${HEADER}" 1152 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1153 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 1154 << "" 1155 << "struct T {" 1156 << " mediump vec3 a;" 1157 << " int b;" 1158 << "};" 1159 << "struct S {" 1160 << " mediump float a;" 1161 << " T b;" 1162 << " int c;" 1163 << "};" 1164 << "" 1165 << "void main (void)" 1166 << "{" 1167 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);" 1168 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);" 1169 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);" 1170 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);" 1171 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 1172 << " if (a == b) ${DST}.x = 1.0;" 1173 << " if (a == c) ${DST}.y = 1.0;" 1174 << " if (a == d) ${DST}.z = 1.0;" 1175 << " ${ASSIGN_POS}" 1176 << "}", 1177 { 1178 instance.useUniform(0u, UI_ONE); 1179 instance.useUniform(1u, UI_TWO); 1180 }, 1181 { 1182 if (deFloatFloor(c.coords[0]) == deFloatFloor(c.coords[0] + 0.5f)) 1183 c.color.x() = 1.0f; 1184 if (deFloatFloor(c.coords[1]) == deFloatFloor(c.coords[1] + 0.5f)) 1185 c.color.y() = 1.0f; 1186 }); 1187 1188 LOCAL_STRUCT_CASE(nested_not_equal, "Nested struct struct equality", 1189 LineStream() 1190 << "${HEADER}" 1191 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1192 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 1193 << "" 1194 << "struct T {" 1195 << " mediump vec3 a;" 1196 << " int b;" 1197 << "};" 1198 << "struct S {" 1199 << " mediump float a;" 1200 << " T b;" 1201 << " int c;" 1202 << "};" 1203 << "" 1204 << "void main (void)" 1205 << "{" 1206 << " S a = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);" 1207 << " S b = S(floor(${COORDS}.x+0.5), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_one), 1);" 1208 << " S c = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y+0.5), 2.3), ui_one), 1);" 1209 << " S d = S(floor(${COORDS}.x), T(vec3(0.0, floor(${COORDS}.y), 2.3), ui_two), 1);" 1210 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 1211 << " if (a != b) ${DST}.x = 1.0;" 1212 << " if (a != c) ${DST}.y = 1.0;" 1213 << " if (a != d) ${DST}.z = 1.0;" 1214 << " ${ASSIGN_POS}" 1215 << "}", 1216 { 1217 instance.useUniform(0u, UI_ONE); 1218 instance.useUniform(1u, UI_TWO); 1219 }, 1220 { 1221 if (deFloatFloor(c.coords[0]) != deFloatFloor(c.coords[0] + 0.5f)) 1222 c.color.x() = 1.0f; 1223 if (deFloatFloor(c.coords[1]) != deFloatFloor(c.coords[1] + 0.5f)) 1224 c.color.y() = 1.0f; 1225 c.color.z() = 1.0f; 1226 }); 1227 } 1228 1229 class UniformStructTests : public tcu::TestCaseGroup 1230 { 1231 public: 1232 UniformStructTests (tcu::TestContext& testCtx) 1233 : TestCaseGroup(testCtx, "uniform", "Uniform structs") 1234 { 1235 } 1236 1237 ~UniformStructTests (void) 1238 { 1239 } 1240 1241 virtual void init (void); 1242 }; 1243 1244 void UniformStructTests::init (void) 1245 { 1246 #define UNIFORM_STRUCT_CASE(NAME, DESCRIPTION, SHADER_SRC, SET_UNIFORMS_BODY, EVAL_FUNC_BODY) \ 1247 do { \ 1248 struct SetUniforms_##NAME { static void setUniforms (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY }; \ 1249 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; \ 1250 addChild(createStructCase(m_testCtx, #NAME "_vertex", DESCRIPTION, true, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \ 1251 addChild(createStructCase(m_testCtx, #NAME "_fragment", DESCRIPTION, false, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \ 1252 } while (deGetFalse()) 1253 1254 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", 1255 LineStream() 1256 << "${HEADER}" 1257 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1258 << "" 1259 << "struct S {" 1260 << " mediump float a;" 1261 << " mediump vec3 b;" 1262 << " int c;" 1263 << "};" 1264 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };" 1265 << "" 1266 << "void main (void)" 1267 << "{" 1268 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 1269 << " ${ASSIGN_POS}" 1270 << "}", 1271 { 1272 instance.useUniform(0u, UI_ONE); 1273 1274 struct S { 1275 float a; 1276 float _padding1[3]; 1277 tcu::Vec3 b; 1278 int c; 1279 }; 1280 1281 S s; 1282 s.a = constCoords.x(); 1283 s.b = constCoords.swizzle(1, 2, 3); 1284 s.c = 1; 1285 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s); 1286 }, 1287 { 1288 c.color.xyz() = c.constCoords.swizzle(0, 1, 2); 1289 }); 1290 1291 UNIFORM_STRUCT_CASE(nested, "Nested struct", 1292 LineStream() 1293 << "${HEADER}" 1294 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1295 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1296 << "" 1297 << "struct T {" 1298 << " int a;" 1299 << " mediump vec2 b;" 1300 << "};" 1301 << "struct S {" 1302 << " mediump float a;" 1303 << " T b;" 1304 << " int c;" 1305 << "};" 1306 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S s; };" 1307 << "" 1308 << "void main (void)" 1309 << "{" 1310 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 1311 << " ${ASSIGN_POS}" 1312 << "}", 1313 { 1314 instance.useUniform(0u, UI_ZERO); 1315 instance.useUniform(1u, UI_ONE); 1316 1317 struct T { 1318 int a; 1319 float _padding1[1]; 1320 tcu::Vec2 b; 1321 }; 1322 1323 struct S { 1324 float a; 1325 float _padding1[3]; 1326 T b; 1327 int c; 1328 float _padding2[3]; 1329 }; 1330 1331 S s; 1332 s.a = constCoords.x(); 1333 s.b.a = 0; 1334 s.b.b = constCoords.swizzle(1, 2); 1335 s.c = 1; 1336 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,sizeof(S), &s); 1337 }, 1338 { 1339 c.color.xyz() = c.constCoords.swizzle(0, 1, 2); 1340 }); 1341 1342 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", 1343 LineStream() 1344 << "${HEADER}" 1345 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1346 << "" 1347 << "struct S {" 1348 << " mediump float a;" 1349 << " mediump float b[3];" 1350 << " int c;" 1351 << "};" 1352 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };" 1353 << "" 1354 << "void main (void)" 1355 << "{" 1356 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" 1357 << " ${ASSIGN_POS}" 1358 << "}", 1359 { 1360 instance.useUniform(0u, UI_ONE); 1361 1362 struct paddedFloat { 1363 float value; 1364 float _padding[3]; 1365 }; 1366 1367 struct S { 1368 paddedFloat a; 1369 paddedFloat b[3]; 1370 int c; 1371 }; 1372 1373 S s; 1374 s.a.value = constCoords.w(); 1375 s.b[0].value = constCoords.z(); 1376 s.b[1].value = constCoords.y(); 1377 s.b[2].value = constCoords.x(); 1378 s.c = 1; 1379 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,sizeof(S), &s); 1380 }, 1381 { 1382 c.color.xyz() = c.constCoords.swizzle(3, 2, 1); 1383 }); 1384 1385 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", 1386 LineStream() 1387 << "${HEADER}" 1388 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1389 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1390 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1391 << "" 1392 << "struct S {" 1393 << " mediump float a;" 1394 << " mediump float b[3];" 1395 << " int c;" 1396 << "};" 1397 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s; };" 1398 << "" 1399 << "void main (void)" 1400 << "{" 1401 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" 1402 << " ${ASSIGN_POS}" 1403 << "}", 1404 { 1405 instance.useUniform(0u, UI_ZERO); 1406 instance.useUniform(1u, UI_ONE); 1407 instance.useUniform(2u, UI_TWO); 1408 1409 struct paddedFloat { 1410 float value; 1411 float _padding[3]; 1412 }; 1413 1414 struct S { 1415 paddedFloat a; 1416 paddedFloat b[3]; 1417 int c; 1418 }; 1419 1420 S s; 1421 s.a.value = constCoords.w(); 1422 s.b[0].value = constCoords.z(); 1423 s.b[1].value = constCoords.y(); 1424 s.b[2].value = constCoords.x(); 1425 s.c = 1; 1426 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s); 1427 }, 1428 { 1429 c.color.xyz() = c.constCoords.swizzle(1, 2, 0); 1430 }); 1431 1432 UNIFORM_STRUCT_CASE(struct_array, "Struct array", 1433 LineStream() 1434 << "${HEADER}" 1435 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1436 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1437 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1438 << "" 1439 << "struct S {" 1440 << " mediump float a;" 1441 << " mediump int b;" 1442 << "};" 1443 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };" 1444 << "" 1445 << "void main (void)" 1446 << "{" 1447 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" 1448 << " ${ASSIGN_POS}" 1449 << "}", 1450 { 1451 instance.useUniform(0u, UI_ZERO); 1452 instance.useUniform(1u, UI_ONE); 1453 instance.useUniform(2u, UI_TWO); 1454 1455 struct S { 1456 float a; 1457 int b; 1458 float _padding1[2]; 1459 }; 1460 1461 S s[3]; 1462 s[0].a = constCoords.x(); 1463 s[0].b = 0; 1464 s[1].a = constCoords.y(); 1465 s[1].b = 1; 1466 s[2].a = constCoords.z(); 1467 s[2].b = 2; 1468 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s); 1469 }, 1470 { 1471 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1472 }); 1473 1474 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", 1475 LineStream() 1476 << "${HEADER}" 1477 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1478 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1479 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1480 << "" 1481 << "struct S {" 1482 << " mediump float a;" 1483 << " mediump int b;" 1484 << "};" 1485 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };" 1486 << "" 1487 << "void main (void)" 1488 << "{" 1489 << " ${DST} = vec4(s[ui_two].a, s[ui_one].a, s[ui_zero].a, s[ui_two].b - s[ui_one].b + s[ui_zero].b);" 1490 << " ${ASSIGN_POS}" 1491 << "}", 1492 { 1493 instance.useUniform(0u, UI_ZERO); 1494 instance.useUniform(1u, UI_ONE); 1495 instance.useUniform(2u, UI_TWO); 1496 1497 struct S { 1498 float a; 1499 int b; 1500 float _padding1[2]; 1501 }; 1502 1503 S s[3]; 1504 s[0].a = constCoords.x(); 1505 s[0].b = 0; 1506 s[1].a = constCoords.y(); 1507 s[1].b = 1; 1508 s[2].a = constCoords.z(); 1509 s[2].b = 2; 1510 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s); 1511 }, 1512 { 1513 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1514 }); 1515 1516 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", 1517 LineStream() 1518 << "${HEADER}" 1519 << "struct T {" 1520 << " mediump float a;" 1521 << " mediump vec2 b[2];" 1522 << "};" 1523 << "struct S {" 1524 << " mediump float a;" 1525 << " T b[3];" 1526 << " int c;" 1527 << "};" 1528 << "layout (std140, set = 0, binding = 0) uniform buffer0 { S s[2]; };" 1529 << "" 1530 << "void main (void)" 1531 << "{" 1532 << " mediump float r = (s[0].b[1].b[0].x + s[1].b[2].b[1].y) * s[0].b[0].a; // (z + z) * 0.5" 1533 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" 1534 << " mediump float b = (s[0].b[2].b[1].y + s[0].b[1].b[0].y + s[1].a) * s[0].b[1].a; // (w + w + w) * 0.333" 1535 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" 1536 << " ${DST} = vec4(r, g, b, a);" 1537 << " ${ASSIGN_POS}" 1538 << "}", 1539 { 1540 1541 struct T { 1542 float a; 1543 float _padding1[3]; 1544 tcu::Vec4 b[2]; 1545 }; 1546 1547 struct S { 1548 float a; 1549 float _padding1[3]; 1550 T b[3]; 1551 int c; 1552 float _padding2[3]; 1553 }; 1554 1555 S s[2]; 1556 s[0].a = constCoords.x(); 1557 s[0].b[0].a = 0.5f; 1558 s[0].b[0].b[0] = constCoords.swizzle(0,1,0,0); 1559 s[0].b[0].b[1] = constCoords.swizzle(2,3,0,0); 1560 s[0].b[1].a = 1.0f / 3.0f; 1561 s[0].b[1].b[0] = constCoords.swizzle(2,3,0,0); 1562 s[0].b[1].b[1] = constCoords.swizzle(0,1,0,0); 1563 s[0].b[2].a = 1.0f / 4.0f; 1564 s[0].b[2].b[0] = constCoords.swizzle(0,2,0,0); 1565 s[0].b[2].b[1] = constCoords.swizzle(1,3,0,0); 1566 s[0].c = 0; 1567 1568 s[1].a = constCoords.w(); 1569 s[1].b[0].a = 2.0f; 1570 s[1].b[0].b[0] = constCoords.swizzle(0,0,0,0); 1571 s[1].b[0].b[1] = constCoords.swizzle(1,1,0,0); 1572 s[1].b[1].a = 3.0f; 1573 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1574 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1575 s[1].b[2].a = 4.0f; 1576 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1577 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1578 s[1].c = 1; 1579 1580 instance.addUniform(0u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1581 }, 1582 { 1583 c.color.xyz() = c.constCoords.swizzle(2, 0, 3); 1584 }); 1585 1586 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", 1587 LineStream() 1588 << "${HEADER}" 1589 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1590 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1591 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1592 << "" 1593 << "struct T {" 1594 << " mediump float a;" 1595 << " mediump vec2 b[2];" 1596 << "};" 1597 << "struct S {" 1598 << " mediump float a;" 1599 << " T b[3];" 1600 << " int c;" 1601 << "};" 1602 << "layout (set = 0, binding = 3) uniform buffer3 { S s[2]; };" 1603 << "" 1604 << "void main (void)" 1605 << "{" 1606 << " mediump float r = (s[0].b[ui_one].b[ui_one-1].x + s[ui_one].b[ui_two].b[ui_zero+1].y) * s[0].b[0].a; // (z + z) * 0.5" 1607 << " mediump float g = s[ui_two-1].b[ui_two-2].b[ui_zero].y * s[0].b[ui_two].a * s[ui_one].b[2].a; // x * 0.25 * 4" 1608 << " mediump float b = (s[ui_zero].b[ui_one+1].b[1].y + s[0].b[ui_one*ui_one].b[0].y + s[ui_one].a) * s[0].b[ui_two-ui_one].a; // (w + w + w) * 0.333" 1609 << " mediump float a = float(s[ui_zero].c) + s[ui_one-ui_zero].b[ui_two].a - s[ui_zero+ui_one].b[ui_two-ui_one].a; // 0 + 4.0 - 3.0" 1610 << " ${DST} = vec4(r, g, b, a);" 1611 << " ${ASSIGN_POS}" 1612 << "}", 1613 { 1614 struct T { 1615 float a; 1616 float _padding1[3]; 1617 tcu::Vec4 b[2]; 1618 }; 1619 1620 struct S { 1621 float a; 1622 float _padding1[3]; 1623 T b[3]; 1624 int c; 1625 float _padding2[3]; 1626 }; 1627 1628 S s[2]; 1629 s[0].a = constCoords.x(); 1630 s[0].b[0].a = 0.5f; 1631 s[0].b[0].b[0] = constCoords.swizzle(0,1,0,0); 1632 s[0].b[0].b[1] = constCoords.swizzle(2,3,0,0); 1633 s[0].b[1].a = 1.0f / 3.0f; 1634 s[0].b[1].b[0] = constCoords.swizzle(2,3,0,0); 1635 s[0].b[1].b[1] = constCoords.swizzle(0,1,0,0); 1636 s[0].b[2].a = 1.0f / 4.0f; 1637 s[0].b[2].b[0] = constCoords.swizzle(0,2,0,0); 1638 s[0].b[2].b[1] = constCoords.swizzle(1,3,0,0); 1639 s[0].c = 0; 1640 1641 s[1].a = constCoords.w(); 1642 s[1].b[0].a = 2.0f; 1643 s[1].b[0].b[0] = constCoords.swizzle(0,0,0,0); 1644 s[1].b[0].b[1] = constCoords.swizzle(1,1,0,0); 1645 s[1].b[1].a = 3.0f; 1646 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1647 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1648 s[1].b[2].a = 4.0f; 1649 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1650 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1651 s[1].c = 1; 1652 1653 instance.useUniform(0u, UI_ZERO); 1654 instance.useUniform(1u, UI_ONE); 1655 instance.useUniform(2u, UI_TWO); 1656 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1657 }, 1658 { 1659 c.color.xyz() = c.constCoords.swizzle(2, 0, 3); 1660 }); 1661 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 1662 LineStream() 1663 << "${HEADER}" 1664 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1665 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1666 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1667 << "" 1668 << "struct S {" 1669 << " mediump float a;" 1670 << " mediump int b;" 1671 << "};" 1672 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };" 1673 << "" 1674 << "void main (void)" 1675 << "{" 1676 << " mediump float rgb[3];" 1677 << " int alpha = 0;" 1678 << " for (int i = 0; i < 3; i++)" 1679 << " {" 1680 << " rgb[i] = s[2-i].a;" 1681 << " alpha += s[i].b;" 1682 << " }" 1683 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 1684 << " ${ASSIGN_POS}" 1685 << "}", 1686 { 1687 instance.useUniform(0u, UI_ZERO); 1688 instance.useUniform(1u, UI_ONE); 1689 instance.useUniform(2u, UI_TWO); 1690 1691 struct S { 1692 float a; 1693 int b; 1694 float _padding1[2]; 1695 }; 1696 1697 S s[3]; 1698 s[0].a = constCoords.x(); 1699 s[0].b = 0; 1700 s[1].a = constCoords.y(); 1701 s[1].b = -1; 1702 s[2].a = constCoords.z(); 1703 s[2].b = 2; 1704 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s); 1705 }, 1706 { 1707 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1708 }); 1709 1710 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 1711 LineStream() 1712 << "${HEADER}" 1713 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1714 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1715 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1716 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };" 1717 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };" 1718 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };" 1719 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };" 1720 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };" 1721 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };" 1722 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };" 1723 << "" 1724 << "struct T {" 1725 << " mediump float a;" 1726 << " mediump vec2 b[2];" 1727 << "};" 1728 << "struct S {" 1729 << " mediump float a;" 1730 << " T b[3];" 1731 << " int c;" 1732 << "};" 1733 << "layout (std140, set = 0, binding = 10) uniform buffer10 { S s[2]; };" 1734 << "" 1735 << "void main (void)" 1736 << "{" 1737 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1738 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1739 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1740 << " mediump float a = 1.0;" 1741 << " for (int i = 0; i < 2; i++)" 1742 << " {" 1743 << " for (int j = 0; j < 3; j++)" 1744 << " {" 1745 << " r += s[0].b[j].b[i].y;" 1746 << " g += s[i].b[j].b[0].x;" 1747 << " b += s[i].b[j].b[1].x;" 1748 << " a *= s[i].b[j].a;" 1749 << " }" 1750 << " }" 1751 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1752 << " ${ASSIGN_POS}" 1753 << "}", 1754 { 1755 instance.useUniform(0u, UI_ZERO); 1756 instance.useUniform(1u, UI_ONE); 1757 instance.useUniform(2u, UI_TWO); 1758 instance.useUniform(3u, UF_TWO); 1759 instance.useUniform(4u, UF_THREE); 1760 instance.useUniform(5u, UF_FOUR); 1761 instance.useUniform(6u, UF_HALF); 1762 instance.useUniform(7u, UF_THIRD); 1763 instance.useUniform(8u, UF_FOURTH); 1764 instance.useUniform(9u, UF_SIXTH); 1765 1766 struct T { 1767 float a; 1768 float _padding1[3]; 1769 tcu::Vec4 b[2]; 1770 }; 1771 1772 struct S { 1773 float a; 1774 float _padding1[3]; 1775 T b[3]; 1776 int c; 1777 float _padding2[3]; 1778 }; 1779 1780 S s[2]; 1781 s[0].a = constCoords.x(); 1782 s[0].b[0].a = 0.5f; 1783 s[0].b[0].b[0] = constCoords.swizzle(1,0,0,0); 1784 s[0].b[0].b[1] = constCoords.swizzle(2,0,0,0); 1785 s[0].b[1].a = 1.0f / 3.0f; 1786 s[0].b[1].b[0] = constCoords.swizzle(1,1,0,0); 1787 s[0].b[1].b[1] = constCoords.swizzle(3,1,0,0); 1788 s[0].b[2].a = 1.0f / 4.0f; 1789 s[0].b[2].b[0] = constCoords.swizzle(2,1,0,0); 1790 s[0].b[2].b[1] = constCoords.swizzle(2,1,0,0); 1791 s[0].c = 0; 1792 1793 s[1].a = constCoords.w(); 1794 s[1].b[0].a = 2.0f; 1795 s[1].b[0].b[0] = constCoords.swizzle(2,0,0,0); 1796 s[1].b[0].b[1] = constCoords.swizzle(2,1,0,0); 1797 s[1].b[1].a = 3.0f; 1798 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1799 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1800 s[1].b[2].a = 4.0f; 1801 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1802 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1803 s[1].c = 1; 1804 1805 instance.addUniform(10u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1806 1807 }, 1808 { 1809 c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; 1810 }); 1811 1812 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", 1813 LineStream() 1814 << "${HEADER}" 1815 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1816 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1817 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1818 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };" 1819 << "" 1820 << "struct S {" 1821 << " mediump float a;" 1822 << " mediump int b;" 1823 << "};" 1824 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S s[3]; };" 1825 << "" 1826 << "void main (void)" 1827 << "{" 1828 << " mediump float rgb[3];" 1829 << " int alpha = 0;" 1830 << " for (int i = 0; i < ui_three; i++)" 1831 << " {" 1832 << " rgb[i] = s[2-i].a;" 1833 << " alpha += s[i].b;" 1834 << " }" 1835 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 1836 << " ${ASSIGN_POS}" 1837 << "}", 1838 { 1839 instance.useUniform(0u, UI_ZERO); 1840 instance.useUniform(1u, UI_ONE); 1841 instance.useUniform(2u, UI_TWO); 1842 instance.useUniform(3u, UI_THREE); 1843 1844 struct S { 1845 float a; 1846 int b; 1847 float _padding1[2]; 1848 }; 1849 1850 S s[3]; 1851 s[0].a = constCoords.x(); 1852 s[0].b = 0; 1853 s[1].a = constCoords.y(); 1854 s[1].b = -1; 1855 s[2].a = constCoords.z(); 1856 s[2].b = 2; 1857 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s); 1858 1859 }, 1860 { 1861 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1862 }); 1863 1864 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", 1865 LineStream() 1866 << "${HEADER}" 1867 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1868 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1869 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1870 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };" 1871 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };" 1872 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };" 1873 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };" 1874 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };" 1875 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };" 1876 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };" 1877 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };" 1878 << "" 1879 << "struct T {" 1880 << " mediump float a;" 1881 << " mediump vec2 b[2];" 1882 << "};" 1883 << "struct S {" 1884 << " mediump float a;" 1885 << " T b[3];" 1886 << " int c;" 1887 << "};" 1888 << "layout (std140, set = 0, binding = 11) uniform buffer11 { S s[2]; };" 1889 << "" 1890 << "void main (void)" 1891 << "{" 1892 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1893 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1894 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1895 << " mediump float a = 1.0;" 1896 << " for (int i = 0; i < ui_two; i++)" 1897 << " {" 1898 << " for (int j = 0; j < ui_three; j++)" 1899 << " {" 1900 << " r += s[0].b[j].b[i].y;" 1901 << " g += s[i].b[j].b[0].x;" 1902 << " b += s[i].b[j].b[1].x;" 1903 << " a *= s[i].b[j].a;" 1904 << " }" 1905 << " }" 1906 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1907 << " ${ASSIGN_POS}" 1908 << "}", 1909 { 1910 instance.useUniform(0u, UI_ZERO); 1911 instance.useUniform(1u, UI_ONE); 1912 instance.useUniform(2u, UI_TWO); 1913 instance.useUniform(3u, UI_THREE); 1914 instance.useUniform(4u, UF_TWO); 1915 instance.useUniform(5u, UF_THREE); 1916 instance.useUniform(6u, UF_FOUR); 1917 instance.useUniform(7u, UF_HALF); 1918 instance.useUniform(8u, UF_THIRD); 1919 instance.useUniform(9u, UF_FOURTH); 1920 instance.useUniform(10u, UF_SIXTH); 1921 1922 struct T { 1923 float a; 1924 float _padding1[3]; 1925 tcu::Vec4 b[2]; 1926 }; 1927 1928 struct S { 1929 float a; 1930 float _padding1[3]; 1931 T b[3]; 1932 int c; 1933 float _padding2[3]; 1934 }; 1935 1936 S s[2]; 1937 s[0].a = constCoords.x(); 1938 s[0].b[0].a = 0.5f; 1939 s[0].b[0].b[0] = constCoords.swizzle(1,0,0,0); 1940 s[0].b[0].b[1] = constCoords.swizzle(2,0,0,0); 1941 s[0].b[1].a = 1.0f / 3.0f; 1942 s[0].b[1].b[0] = constCoords.swizzle(1,1,0,0); 1943 s[0].b[1].b[1] = constCoords.swizzle(3,1,0,0); 1944 s[0].b[2].a = 1.0f / 4.0f; 1945 s[0].b[2].b[0] = constCoords.swizzle(2,1,0,0); 1946 s[0].b[2].b[1] = constCoords.swizzle(2,1,0,0); 1947 s[0].c = 0; 1948 1949 s[1].a = constCoords.w(); 1950 s[1].b[0].a = 2.0f; 1951 s[1].b[0].b[0] = constCoords.swizzle(2,0,0,0); 1952 s[1].b[0].b[1] = constCoords.swizzle(2,1,0,0); 1953 s[1].b[1].a = 3.0f; 1954 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1955 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1956 s[1].b[2].a = 4.0f; 1957 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1958 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1959 s[1].c = 1; 1960 1961 instance.addUniform(11u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1962 1963 }, 1964 { 1965 c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; 1966 }); 1967 1968 UNIFORM_STRUCT_CASE(equal, "Struct equality", 1969 LineStream() 1970 << "${HEADER}" 1971 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };" 1972 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 1973 << "" 1974 << "struct S {" 1975 << " mediump float a;" 1976 << " mediump vec3 b;" 1977 << " int c;" 1978 << "};" 1979 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };" 1980 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };" 1981 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };" 1982 << "" 1983 << "void main (void)" 1984 << "{" 1985 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);" 1986 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 1987 << " if (a == b) ${DST}.x = 1.0;" 1988 << " if (a == c) ${DST}.y = 1.0;" 1989 << " if (a == d) ${DST}.z = 1.0;" 1990 << " ${ASSIGN_POS}" 1991 << "}", 1992 { 1993 DE_UNREF(constCoords); 1994 instance.useUniform(0u, UF_ONE); 1995 instance.useUniform(1u, UI_TWO); 1996 1997 struct S { 1998 float a; 1999 float _padding1[3]; 2000 tcu::Vec3 b; 2001 int c; 2002 }; 2003 2004 S sa; 2005 sa.a = 1.0f; 2006 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2007 sa.c = 2; 2008 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa); 2009 2010 S sb; 2011 sb.a = 1.0f; 2012 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2013 sb.c = 2; 2014 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb); 2015 2016 S sc; 2017 sc.a = 1.0f; 2018 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f); 2019 sc.c = 2; 2020 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc); 2021 }, 2022 { 2023 c.color.xy() = tcu::Vec2(1.0f, 0.0f); 2024 if (deFloatFloor(c.coords[1] + 1.0f) == deFloatFloor(1.1f)) 2025 c.color.z() = 1.0f; 2026 }); 2027 2028 UNIFORM_STRUCT_CASE(not_equal, "Struct equality", 2029 LineStream() 2030 << "${HEADER}" 2031 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };" 2032 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 2033 << "" 2034 << "struct S {" 2035 << " mediump float a;" 2036 << " mediump vec3 b;" 2037 << " int c;" 2038 << "};" 2039 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };" 2040 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };" 2041 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };" 2042 << "" 2043 << "void main (void)" 2044 << "{" 2045 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);" 2046 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 2047 << " if (a != b) ${DST}.x = 1.0;" 2048 << " if (a != c) ${DST}.y = 1.0;" 2049 << " if (a != d) ${DST}.z = 1.0;" 2050 << " ${ASSIGN_POS}" 2051 << "}", 2052 { 2053 DE_UNREF(constCoords); 2054 instance.useUniform(0u, UF_ONE); 2055 instance.useUniform(1u, UI_TWO); 2056 2057 struct S { 2058 float a; 2059 float _padding1[3]; 2060 tcu::Vec3 b; 2061 int c; 2062 }; 2063 2064 S sa; 2065 sa.a = 1.0f; 2066 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2067 sa.c = 2; 2068 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa); 2069 2070 S sb; 2071 sb.a = 1.0f; 2072 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2073 sb.c = 2; 2074 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb); 2075 2076 S sc; 2077 sc.a = 1.0f; 2078 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f); 2079 sc.c = 2; 2080 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc); 2081 }, 2082 { 2083 c.color.xy() = tcu::Vec2(0.0f, 1.0f); 2084 if (deFloatFloor(c.coords[1] + 1.0f) != deFloatFloor(1.1f)) 2085 c.color.z() = 1.0f; 2086 }); 2087 } 2088 2089 class ShaderStructTests : public tcu::TestCaseGroup 2090 { 2091 public: 2092 ShaderStructTests (tcu::TestContext& context); 2093 virtual ~ShaderStructTests (void); 2094 2095 virtual void init (void); 2096 2097 private: 2098 ShaderStructTests (const ShaderStructTests&); // not allowed! 2099 ShaderStructTests& operator= (const ShaderStructTests&); // not allowed! 2100 }; 2101 2102 ShaderStructTests::ShaderStructTests (tcu::TestContext& testCtx) 2103 : TestCaseGroup(testCtx, "struct", "Struct Tests") 2104 { 2105 } 2106 2107 ShaderStructTests::~ShaderStructTests (void) 2108 { 2109 } 2110 2111 void ShaderStructTests::init (void) 2112 { 2113 addChild(new LocalStructTests(m_testCtx)); 2114 addChild(new UniformStructTests(m_testCtx)); 2115 } 2116 2117 } // anonymous 2118 2119 tcu::TestCaseGroup* createStructTests (tcu::TestContext& testCtx) 2120 { 2121 return new ShaderStructTests(testCtx); 2122 } 2123 2124 } // sr 2125 } // vkt 2126