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 31namespace vkt 32{ 33namespace sr 34{ 35namespace 36{ 37 38class ShaderStructCase : public ShaderRenderCase 39{ 40public: 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 51private: 52 ShaderStructCase (const ShaderStructCase&); 53 ShaderStructCase& operator= (const ShaderStructCase&); 54}; 55 56ShaderStructCase::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 70ShaderStructCase::~ShaderStructCase (void) 71{ 72} 73 74static 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 131class LocalStructTests : public tcu::TestCaseGroup 132{ 133public: 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 146void 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 }; /* NOLINT(SET_UNIFORMS_BODY) */ \ 151 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(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 1229class UniformStructTests : public tcu::TestCaseGroup 1230{ 1231public: 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 1244void 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 { \ 1249 static void setUniforms (ShaderRenderCaseInstance& instance, const tcu::Vec4& constCoords) SET_UNIFORMS_BODY /* NOLINT(SET_UNIFORMS_BODY) */ \ 1250 }; \ 1251 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; /* NOLINT(EVAL_FUNC_BODY) */ \ 1252 addChild(createStructCase(m_testCtx, #NAME "_vertex", DESCRIPTION, true, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \ 1253 addChild(createStructCase(m_testCtx, #NAME "_fragment", DESCRIPTION, false, Eval_##NAME::eval, SetUniforms_##NAME::setUniforms, SHADER_SRC).release()); \ 1254 } while (deGetFalse()) 1255 1256 UNIFORM_STRUCT_CASE(basic, "Basic struct usage", 1257 LineStream() 1258 << "${HEADER}" 1259 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1260 << "" 1261 << "struct S {" 1262 << " mediump float a;" 1263 << " mediump vec3 b;" 1264 << " int c;" 1265 << "};" 1266 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };" 1267 << "" 1268 << "void main (void)" 1269 << "{" 1270 << " ${DST} = vec4(s.a, s.b.x, s.b.y, s.c);" 1271 << " ${ASSIGN_POS}" 1272 << "}", 1273 { 1274 instance.useUniform(0u, UI_ONE); 1275 1276 struct S { 1277 float a; 1278 float _padding1[3]; 1279 tcu::Vec3 b; 1280 int c; 1281 }; 1282 1283 S s; 1284 s.a = constCoords.x(); 1285 s.b = constCoords.swizzle(1, 2, 3); 1286 s.c = 1; 1287 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s); 1288 }, 1289 { 1290 c.color.xyz() = c.constCoords.swizzle(0, 1, 2); 1291 }); 1292 1293 UNIFORM_STRUCT_CASE(nested, "Nested struct", 1294 LineStream() 1295 << "${HEADER}" 1296 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1297 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1298 << "" 1299 << "struct T {" 1300 << " int a;" 1301 << " mediump vec2 b;" 1302 << "};" 1303 << "struct S {" 1304 << " mediump float a;" 1305 << " T b;" 1306 << " int c;" 1307 << "};" 1308 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S s; };" 1309 << "" 1310 << "void main (void)" 1311 << "{" 1312 << " ${DST} = vec4(s.a, s.b.b, s.b.a + s.c);" 1313 << " ${ASSIGN_POS}" 1314 << "}", 1315 { 1316 instance.useUniform(0u, UI_ZERO); 1317 instance.useUniform(1u, UI_ONE); 1318 1319 struct T { 1320 int a; 1321 float _padding1[1]; 1322 tcu::Vec2 b; 1323 }; 1324 1325 struct S { 1326 float a; 1327 float _padding1[3]; 1328 T b; 1329 int c; 1330 float _padding2[3]; 1331 }; 1332 1333 S s; 1334 s.a = constCoords.x(); 1335 s.b.a = 0; 1336 s.b.b = constCoords.swizzle(1, 2); 1337 s.c = 1; 1338 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,sizeof(S), &s); 1339 }, 1340 { 1341 c.color.xyz() = c.constCoords.swizzle(0, 1, 2); 1342 }); 1343 1344 UNIFORM_STRUCT_CASE(array_member, "Struct with array member", 1345 LineStream() 1346 << "${HEADER}" 1347 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_one; };" 1348 << "" 1349 << "struct S {" 1350 << " mediump float a;" 1351 << " mediump float b[3];" 1352 << " int c;" 1353 << "};" 1354 << "layout (std140, set = 0, binding = 1) uniform buffer1 { S s; };" 1355 << "" 1356 << "void main (void)" 1357 << "{" 1358 << " ${DST} = vec4(s.a, s.b[0], s.b[1], s.c);" 1359 << " ${ASSIGN_POS}" 1360 << "}", 1361 { 1362 instance.useUniform(0u, UI_ONE); 1363 1364 struct paddedFloat { 1365 float value; 1366 float _padding[3]; 1367 }; 1368 1369 struct S { 1370 paddedFloat a; 1371 paddedFloat b[3]; 1372 int c; 1373 }; 1374 1375 S s; 1376 s.a.value = constCoords.w(); 1377 s.b[0].value = constCoords.z(); 1378 s.b[1].value = constCoords.y(); 1379 s.b[2].value = constCoords.x(); 1380 s.c = 1; 1381 instance.addUniform(1u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,sizeof(S), &s); 1382 }, 1383 { 1384 c.color.xyz() = c.constCoords.swizzle(3, 2, 1); 1385 }); 1386 1387 UNIFORM_STRUCT_CASE(array_member_dynamic_index, "Struct with array member, dynamic indexing", 1388 LineStream() 1389 << "${HEADER}" 1390 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1391 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1392 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1393 << "" 1394 << "struct S {" 1395 << " mediump float a;" 1396 << " mediump float b[3];" 1397 << " int c;" 1398 << "};" 1399 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s; };" 1400 << "" 1401 << "void main (void)" 1402 << "{" 1403 << " ${DST} = vec4(s.b[ui_one], s.b[ui_zero], s.b[ui_two], s.c);" 1404 << " ${ASSIGN_POS}" 1405 << "}", 1406 { 1407 instance.useUniform(0u, UI_ZERO); 1408 instance.useUniform(1u, UI_ONE); 1409 instance.useUniform(2u, UI_TWO); 1410 1411 struct paddedFloat { 1412 float value; 1413 float _padding[3]; 1414 }; 1415 1416 struct S { 1417 paddedFloat a; 1418 paddedFloat b[3]; 1419 int c; 1420 }; 1421 1422 S s; 1423 s.a.value = constCoords.w(); 1424 s.b[0].value = constCoords.z(); 1425 s.b[1].value = constCoords.y(); 1426 s.b[2].value = constCoords.x(); 1427 s.c = 1; 1428 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &s); 1429 }, 1430 { 1431 c.color.xyz() = c.constCoords.swizzle(1, 2, 0); 1432 }); 1433 1434 UNIFORM_STRUCT_CASE(struct_array, "Struct array", 1435 LineStream() 1436 << "${HEADER}" 1437 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1438 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1439 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1440 << "" 1441 << "struct S {" 1442 << " mediump float a;" 1443 << " mediump int b;" 1444 << "};" 1445 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };" 1446 << "" 1447 << "void main (void)" 1448 << "{" 1449 << " ${DST} = vec4(s[2].a, s[1].a, s[0].a, s[2].b - s[1].b + s[0].b);" 1450 << " ${ASSIGN_POS}" 1451 << "}", 1452 { 1453 instance.useUniform(0u, UI_ZERO); 1454 instance.useUniform(1u, UI_ONE); 1455 instance.useUniform(2u, UI_TWO); 1456 1457 struct S { 1458 float a; 1459 int b; 1460 float _padding1[2]; 1461 }; 1462 1463 S s[3]; 1464 s[0].a = constCoords.x(); 1465 s[0].b = 0; 1466 s[1].a = constCoords.y(); 1467 s[1].b = 1; 1468 s[2].a = constCoords.z(); 1469 s[2].b = 2; 1470 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s); 1471 }, 1472 { 1473 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1474 }); 1475 1476 UNIFORM_STRUCT_CASE(struct_array_dynamic_index, "Struct array with dynamic indexing", 1477 LineStream() 1478 << "${HEADER}" 1479 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1480 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1481 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1482 << "" 1483 << "struct S {" 1484 << " mediump float a;" 1485 << " mediump int b;" 1486 << "};" 1487 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };" 1488 << "" 1489 << "void main (void)" 1490 << "{" 1491 << " ${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);" 1492 << " ${ASSIGN_POS}" 1493 << "}", 1494 { 1495 instance.useUniform(0u, UI_ZERO); 1496 instance.useUniform(1u, UI_ONE); 1497 instance.useUniform(2u, UI_TWO); 1498 1499 struct S { 1500 float a; 1501 int b; 1502 float _padding1[2]; 1503 }; 1504 1505 S s[3]; 1506 s[0].a = constCoords.x(); 1507 s[0].b = 0; 1508 s[1].a = constCoords.y(); 1509 s[1].b = 1; 1510 s[2].a = constCoords.z(); 1511 s[2].b = 2; 1512 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3 * sizeof(S), s); 1513 }, 1514 { 1515 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1516 }); 1517 1518 UNIFORM_STRUCT_CASE(nested_struct_array, "Nested struct array", 1519 LineStream() 1520 << "${HEADER}" 1521 << "struct T {" 1522 << " mediump float a;" 1523 << " mediump vec2 b[2];" 1524 << "};" 1525 << "struct S {" 1526 << " mediump float a;" 1527 << " T b[3];" 1528 << " int c;" 1529 << "};" 1530 << "layout (std140, set = 0, binding = 0) uniform buffer0 { S s[2]; };" 1531 << "" 1532 << "void main (void)" 1533 << "{" 1534 << " 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" 1535 << " mediump float g = s[1].b[0].b[0].y * s[0].b[2].a * s[1].b[2].a; // x * 0.25 * 4" 1536 << " 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" 1537 << " mediump float a = float(s[0].c) + s[1].b[2].a - s[1].b[1].a; // 0 + 4.0 - 3.0" 1538 << " ${DST} = vec4(r, g, b, a);" 1539 << " ${ASSIGN_POS}" 1540 << "}", 1541 { 1542 1543 struct T { 1544 float a; 1545 float _padding1[3]; 1546 tcu::Vec4 b[2]; 1547 }; 1548 1549 struct S { 1550 float a; 1551 float _padding1[3]; 1552 T b[3]; 1553 int c; 1554 float _padding2[3]; 1555 }; 1556 1557 S s[2]; 1558 s[0].a = constCoords.x(); 1559 s[0].b[0].a = 0.5f; 1560 s[0].b[0].b[0] = constCoords.swizzle(0,1,0,0); 1561 s[0].b[0].b[1] = constCoords.swizzle(2,3,0,0); 1562 s[0].b[1].a = 1.0f / 3.0f; 1563 s[0].b[1].b[0] = constCoords.swizzle(2,3,0,0); 1564 s[0].b[1].b[1] = constCoords.swizzle(0,1,0,0); 1565 s[0].b[2].a = 1.0f / 4.0f; 1566 s[0].b[2].b[0] = constCoords.swizzle(0,2,0,0); 1567 s[0].b[2].b[1] = constCoords.swizzle(1,3,0,0); 1568 s[0].c = 0; 1569 1570 s[1].a = constCoords.w(); 1571 s[1].b[0].a = 2.0f; 1572 s[1].b[0].b[0] = constCoords.swizzle(0,0,0,0); 1573 s[1].b[0].b[1] = constCoords.swizzle(1,1,0,0); 1574 s[1].b[1].a = 3.0f; 1575 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1576 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1577 s[1].b[2].a = 4.0f; 1578 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1579 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1580 s[1].c = 1; 1581 1582 instance.addUniform(0u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1583 }, 1584 { 1585 c.color.xyz() = c.constCoords.swizzle(2, 0, 3); 1586 }); 1587 1588 UNIFORM_STRUCT_CASE(nested_struct_array_dynamic_index, "Nested struct array with dynamic indexing", 1589 LineStream() 1590 << "${HEADER}" 1591 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1592 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1593 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1594 << "" 1595 << "struct T {" 1596 << " mediump float a;" 1597 << " mediump vec2 b[2];" 1598 << "};" 1599 << "struct S {" 1600 << " mediump float a;" 1601 << " T b[3];" 1602 << " int c;" 1603 << "};" 1604 << "layout (set = 0, binding = 3) uniform buffer3 { S s[2]; };" 1605 << "" 1606 << "void main (void)" 1607 << "{" 1608 << " 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" 1609 << " 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" 1610 << " 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" 1611 << " 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" 1612 << " ${DST} = vec4(r, g, b, a);" 1613 << " ${ASSIGN_POS}" 1614 << "}", 1615 { 1616 struct T { 1617 float a; 1618 float _padding1[3]; 1619 tcu::Vec4 b[2]; 1620 }; 1621 1622 struct S { 1623 float a; 1624 float _padding1[3]; 1625 T b[3]; 1626 int c; 1627 float _padding2[3]; 1628 }; 1629 1630 S s[2]; 1631 s[0].a = constCoords.x(); 1632 s[0].b[0].a = 0.5f; 1633 s[0].b[0].b[0] = constCoords.swizzle(0,1,0,0); 1634 s[0].b[0].b[1] = constCoords.swizzle(2,3,0,0); 1635 s[0].b[1].a = 1.0f / 3.0f; 1636 s[0].b[1].b[0] = constCoords.swizzle(2,3,0,0); 1637 s[0].b[1].b[1] = constCoords.swizzle(0,1,0,0); 1638 s[0].b[2].a = 1.0f / 4.0f; 1639 s[0].b[2].b[0] = constCoords.swizzle(0,2,0,0); 1640 s[0].b[2].b[1] = constCoords.swizzle(1,3,0,0); 1641 s[0].c = 0; 1642 1643 s[1].a = constCoords.w(); 1644 s[1].b[0].a = 2.0f; 1645 s[1].b[0].b[0] = constCoords.swizzle(0,0,0,0); 1646 s[1].b[0].b[1] = constCoords.swizzle(1,1,0,0); 1647 s[1].b[1].a = 3.0f; 1648 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1649 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1650 s[1].b[2].a = 4.0f; 1651 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1652 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1653 s[1].c = 1; 1654 1655 instance.useUniform(0u, UI_ZERO); 1656 instance.useUniform(1u, UI_ONE); 1657 instance.useUniform(2u, UI_TWO); 1658 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1659 }, 1660 { 1661 c.color.xyz() = c.constCoords.swizzle(2, 0, 3); 1662 }); 1663 UNIFORM_STRUCT_CASE(loop_struct_array, "Struct array usage in loop", 1664 LineStream() 1665 << "${HEADER}" 1666 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1667 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1668 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1669 << "" 1670 << "struct S {" 1671 << " mediump float a;" 1672 << " mediump int b;" 1673 << "};" 1674 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S s[3]; };" 1675 << "" 1676 << "void main (void)" 1677 << "{" 1678 << " mediump float rgb[3];" 1679 << " int alpha = 0;" 1680 << " for (int i = 0; i < 3; i++)" 1681 << " {" 1682 << " rgb[i] = s[2-i].a;" 1683 << " alpha += s[i].b;" 1684 << " }" 1685 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 1686 << " ${ASSIGN_POS}" 1687 << "}", 1688 { 1689 instance.useUniform(0u, UI_ZERO); 1690 instance.useUniform(1u, UI_ONE); 1691 instance.useUniform(2u, UI_TWO); 1692 1693 struct S { 1694 float a; 1695 int b; 1696 float _padding1[2]; 1697 }; 1698 1699 S s[3]; 1700 s[0].a = constCoords.x(); 1701 s[0].b = 0; 1702 s[1].a = constCoords.y(); 1703 s[1].b = -1; 1704 s[2].a = constCoords.z(); 1705 s[2].b = 2; 1706 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s); 1707 }, 1708 { 1709 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1710 }); 1711 1712 UNIFORM_STRUCT_CASE(loop_nested_struct_array, "Nested struct array usage in loop", 1713 LineStream() 1714 << "${HEADER}" 1715 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1716 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1717 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1718 << "layout (std140, set = 0, binding = 3) uniform buffer3 { mediump float uf_two; };" 1719 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_three; };" 1720 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_four; };" 1721 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_half; };" 1722 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_third; };" 1723 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_fourth; };" 1724 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_sixth; };" 1725 << "" 1726 << "struct T {" 1727 << " mediump float a;" 1728 << " mediump vec2 b[2];" 1729 << "};" 1730 << "struct S {" 1731 << " mediump float a;" 1732 << " T b[3];" 1733 << " int c;" 1734 << "};" 1735 << "layout (std140, set = 0, binding = 10) uniform buffer10 { S s[2]; };" 1736 << "" 1737 << "void main (void)" 1738 << "{" 1739 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1740 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1741 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1742 << " mediump float a = 1.0;" 1743 << " for (int i = 0; i < 2; i++)" 1744 << " {" 1745 << " for (int j = 0; j < 3; j++)" 1746 << " {" 1747 << " r += s[0].b[j].b[i].y;" 1748 << " g += s[i].b[j].b[0].x;" 1749 << " b += s[i].b[j].b[1].x;" 1750 << " a *= s[i].b[j].a;" 1751 << " }" 1752 << " }" 1753 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1754 << " ${ASSIGN_POS}" 1755 << "}", 1756 { 1757 instance.useUniform(0u, UI_ZERO); 1758 instance.useUniform(1u, UI_ONE); 1759 instance.useUniform(2u, UI_TWO); 1760 instance.useUniform(3u, UF_TWO); 1761 instance.useUniform(4u, UF_THREE); 1762 instance.useUniform(5u, UF_FOUR); 1763 instance.useUniform(6u, UF_HALF); 1764 instance.useUniform(7u, UF_THIRD); 1765 instance.useUniform(8u, UF_FOURTH); 1766 instance.useUniform(9u, UF_SIXTH); 1767 1768 struct T { 1769 float a; 1770 float _padding1[3]; 1771 tcu::Vec4 b[2]; 1772 }; 1773 1774 struct S { 1775 float a; 1776 float _padding1[3]; 1777 T b[3]; 1778 int c; 1779 float _padding2[3]; 1780 }; 1781 1782 S s[2]; 1783 s[0].a = constCoords.x(); 1784 s[0].b[0].a = 0.5f; 1785 s[0].b[0].b[0] = constCoords.swizzle(1,0,0,0); 1786 s[0].b[0].b[1] = constCoords.swizzle(2,0,0,0); 1787 s[0].b[1].a = 1.0f / 3.0f; 1788 s[0].b[1].b[0] = constCoords.swizzle(1,1,0,0); 1789 s[0].b[1].b[1] = constCoords.swizzle(3,1,0,0); 1790 s[0].b[2].a = 1.0f / 4.0f; 1791 s[0].b[2].b[0] = constCoords.swizzle(2,1,0,0); 1792 s[0].b[2].b[1] = constCoords.swizzle(2,1,0,0); 1793 s[0].c = 0; 1794 1795 s[1].a = constCoords.w(); 1796 s[1].b[0].a = 2.0f; 1797 s[1].b[0].b[0] = constCoords.swizzle(2,0,0,0); 1798 s[1].b[0].b[1] = constCoords.swizzle(2,1,0,0); 1799 s[1].b[1].a = 3.0f; 1800 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1801 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1802 s[1].b[2].a = 4.0f; 1803 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1804 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1805 s[1].c = 1; 1806 1807 instance.addUniform(10u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1808 1809 }, 1810 { 1811 c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; 1812 }); 1813 1814 UNIFORM_STRUCT_CASE(dynamic_loop_struct_array, "Struct array usage in dynamic loop", 1815 LineStream() 1816 << "${HEADER}" 1817 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1818 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1819 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1820 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };" 1821 << "" 1822 << "struct S {" 1823 << " mediump float a;" 1824 << " mediump int b;" 1825 << "};" 1826 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S s[3]; };" 1827 << "" 1828 << "void main (void)" 1829 << "{" 1830 << " mediump float rgb[3];" 1831 << " int alpha = 0;" 1832 << " for (int i = 0; i < ui_three; i++)" 1833 << " {" 1834 << " rgb[i] = s[2-i].a;" 1835 << " alpha += s[i].b;" 1836 << " }" 1837 << " ${DST} = vec4(rgb[0], rgb[1], rgb[2], alpha);" 1838 << " ${ASSIGN_POS}" 1839 << "}", 1840 { 1841 instance.useUniform(0u, UI_ZERO); 1842 instance.useUniform(1u, UI_ONE); 1843 instance.useUniform(2u, UI_TWO); 1844 instance.useUniform(3u, UI_THREE); 1845 1846 struct S { 1847 float a; 1848 int b; 1849 float _padding1[2]; 1850 }; 1851 1852 S s[3]; 1853 s[0].a = constCoords.x(); 1854 s[0].b = 0; 1855 s[1].a = constCoords.y(); 1856 s[1].b = -1; 1857 s[2].a = constCoords.z(); 1858 s[2].b = 2; 1859 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3u * sizeof(S), s); 1860 1861 }, 1862 { 1863 c.color.xyz() = c.constCoords.swizzle(2, 1, 0); 1864 }); 1865 1866 UNIFORM_STRUCT_CASE(dynamic_loop_nested_struct_array, "Nested struct array usage in dynamic loop", 1867 LineStream() 1868 << "${HEADER}" 1869 << "layout (std140, set = 0, binding = 0) uniform buffer0 { int ui_zero; };" 1870 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_one; };" 1871 << "layout (std140, set = 0, binding = 2) uniform buffer2 { int ui_two; };" 1872 << "layout (std140, set = 0, binding = 3) uniform buffer3 { int ui_three; };" 1873 << "layout (std140, set = 0, binding = 4) uniform buffer4 { mediump float uf_two; };" 1874 << "layout (std140, set = 0, binding = 5) uniform buffer5 { mediump float uf_three; };" 1875 << "layout (std140, set = 0, binding = 6) uniform buffer6 { mediump float uf_four; };" 1876 << "layout (std140, set = 0, binding = 7) uniform buffer7 { mediump float uf_half; };" 1877 << "layout (std140, set = 0, binding = 8) uniform buffer8 { mediump float uf_third; };" 1878 << "layout (std140, set = 0, binding = 9) uniform buffer9 { mediump float uf_fourth; };" 1879 << "layout (std140, set = 0, binding = 10) uniform buffer10 { mediump float uf_sixth; };" 1880 << "" 1881 << "struct T {" 1882 << " mediump float a;" 1883 << " mediump vec2 b[2];" 1884 << "};" 1885 << "struct S {" 1886 << " mediump float a;" 1887 << " T b[3];" 1888 << " int c;" 1889 << "};" 1890 << "layout (std140, set = 0, binding = 11) uniform buffer11 { S s[2]; };" 1891 << "" 1892 << "void main (void)" 1893 << "{" 1894 << " mediump float r = 0.0; // (x*3 + y*3) / 6.0" 1895 << " mediump float g = 0.0; // (y*3 + z*3) / 6.0" 1896 << " mediump float b = 0.0; // (z*3 + w*3) / 6.0" 1897 << " mediump float a = 1.0;" 1898 << " for (int i = 0; i < ui_two; i++)" 1899 << " {" 1900 << " for (int j = 0; j < ui_three; j++)" 1901 << " {" 1902 << " r += s[0].b[j].b[i].y;" 1903 << " g += s[i].b[j].b[0].x;" 1904 << " b += s[i].b[j].b[1].x;" 1905 << " a *= s[i].b[j].a;" 1906 << " }" 1907 << " }" 1908 << " ${DST} = vec4(r*uf_sixth, g*uf_sixth, b*uf_sixth, a);" 1909 << " ${ASSIGN_POS}" 1910 << "}", 1911 { 1912 instance.useUniform(0u, UI_ZERO); 1913 instance.useUniform(1u, UI_ONE); 1914 instance.useUniform(2u, UI_TWO); 1915 instance.useUniform(3u, UI_THREE); 1916 instance.useUniform(4u, UF_TWO); 1917 instance.useUniform(5u, UF_THREE); 1918 instance.useUniform(6u, UF_FOUR); 1919 instance.useUniform(7u, UF_HALF); 1920 instance.useUniform(8u, UF_THIRD); 1921 instance.useUniform(9u, UF_FOURTH); 1922 instance.useUniform(10u, UF_SIXTH); 1923 1924 struct T { 1925 float a; 1926 float _padding1[3]; 1927 tcu::Vec4 b[2]; 1928 }; 1929 1930 struct S { 1931 float a; 1932 float _padding1[3]; 1933 T b[3]; 1934 int c; 1935 float _padding2[3]; 1936 }; 1937 1938 S s[2]; 1939 s[0].a = constCoords.x(); 1940 s[0].b[0].a = 0.5f; 1941 s[0].b[0].b[0] = constCoords.swizzle(1,0,0,0); 1942 s[0].b[0].b[1] = constCoords.swizzle(2,0,0,0); 1943 s[0].b[1].a = 1.0f / 3.0f; 1944 s[0].b[1].b[0] = constCoords.swizzle(1,1,0,0); 1945 s[0].b[1].b[1] = constCoords.swizzle(3,1,0,0); 1946 s[0].b[2].a = 1.0f / 4.0f; 1947 s[0].b[2].b[0] = constCoords.swizzle(2,1,0,0); 1948 s[0].b[2].b[1] = constCoords.swizzle(2,1,0,0); 1949 s[0].c = 0; 1950 1951 s[1].a = constCoords.w(); 1952 s[1].b[0].a = 2.0f; 1953 s[1].b[0].b[0] = constCoords.swizzle(2,0,0,0); 1954 s[1].b[0].b[1] = constCoords.swizzle(2,1,0,0); 1955 s[1].b[1].a = 3.0f; 1956 s[1].b[1].b[0] = constCoords.swizzle(2,2,0,0); 1957 s[1].b[1].b[1] = constCoords.swizzle(3,3,0,0); 1958 s[1].b[2].a = 4.0f; 1959 s[1].b[2].b[0] = constCoords.swizzle(1,0,0,0); 1960 s[1].b[2].b[1] = constCoords.swizzle(3,2,0,0); 1961 s[1].c = 1; 1962 1963 instance.addUniform(11u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 * sizeof(S), s); 1964 1965 }, 1966 { 1967 c.color.xyz() = (c.constCoords.swizzle(0, 1, 2) + c.constCoords.swizzle(1, 2, 3)) * 0.5f; 1968 }); 1969 1970 UNIFORM_STRUCT_CASE(equal, "Struct equality", 1971 LineStream() 1972 << "${HEADER}" 1973 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };" 1974 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 1975 << "" 1976 << "struct S {" 1977 << " mediump float a;" 1978 << " mediump vec3 b;" 1979 << " int c;" 1980 << "};" 1981 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };" 1982 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };" 1983 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };" 1984 << "" 1985 << "void main (void)" 1986 << "{" 1987 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);" 1988 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 1989 << " if (a == b) ${DST}.x = 1.0;" 1990 << " if (a == c) ${DST}.y = 1.0;" 1991 << " if (a == d) ${DST}.z = 1.0;" 1992 << " ${ASSIGN_POS}" 1993 << "}", 1994 { 1995 DE_UNREF(constCoords); 1996 instance.useUniform(0u, UF_ONE); 1997 instance.useUniform(1u, UI_TWO); 1998 1999 struct S { 2000 float a; 2001 float _padding1[3]; 2002 tcu::Vec3 b; 2003 int c; 2004 }; 2005 2006 S sa; 2007 sa.a = 1.0f; 2008 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2009 sa.c = 2; 2010 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa); 2011 2012 S sb; 2013 sb.a = 1.0f; 2014 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2015 sb.c = 2; 2016 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb); 2017 2018 S sc; 2019 sc.a = 1.0f; 2020 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f); 2021 sc.c = 2; 2022 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc); 2023 }, 2024 { 2025 c.color.xy() = tcu::Vec2(1.0f, 0.0f); 2026 if (deFloatFloor(c.coords[1] + 1.0f) == deFloatFloor(1.1f)) 2027 c.color.z() = 1.0f; 2028 }); 2029 2030 UNIFORM_STRUCT_CASE(not_equal, "Struct equality", 2031 LineStream() 2032 << "${HEADER}" 2033 << "layout (std140, set = 0, binding = 0) uniform buffer0 { mediump float uf_one; };" 2034 << "layout (std140, set = 0, binding = 1) uniform buffer1 { int ui_two; };" 2035 << "" 2036 << "struct S {" 2037 << " mediump float a;" 2038 << " mediump vec3 b;" 2039 << " int c;" 2040 << "};" 2041 << "layout (std140, set = 0, binding = 2) uniform buffer2 { S a; };" 2042 << "layout (std140, set = 0, binding = 3) uniform buffer3 { S b; };" 2043 << "layout (std140, set = 0, binding = 4) uniform buffer4 { S c; };" 2044 << "" 2045 << "void main (void)" 2046 << "{" 2047 << " S d = S(uf_one, vec3(0.0, floor(${COORDS}.y+1.0), 2.0), ui_two);" 2048 << " ${DST} = vec4(0.0, 0.0, 0.0, 1.0);" 2049 << " if (a != b) ${DST}.x = 1.0;" 2050 << " if (a != c) ${DST}.y = 1.0;" 2051 << " if (a != d) ${DST}.z = 1.0;" 2052 << " ${ASSIGN_POS}" 2053 << "}", 2054 { 2055 DE_UNREF(constCoords); 2056 instance.useUniform(0u, UF_ONE); 2057 instance.useUniform(1u, UI_TWO); 2058 2059 struct S { 2060 float a; 2061 float _padding1[3]; 2062 tcu::Vec3 b; 2063 int c; 2064 }; 2065 2066 S sa; 2067 sa.a = 1.0f; 2068 sa.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2069 sa.c = 2; 2070 instance.addUniform(2u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sa); 2071 2072 S sb; 2073 sb.a = 1.0f; 2074 sb.b = tcu::Vec3(0.0f, 1.0f, 2.0f); 2075 sb.c = 2; 2076 instance.addUniform(3u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sb); 2077 2078 S sc; 2079 sc.a = 1.0f; 2080 sc.b = tcu::Vec3(0.0f, 1.1f, 2.0f); 2081 sc.c = 2; 2082 instance.addUniform(4u, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(S), &sc); 2083 }, 2084 { 2085 c.color.xy() = tcu::Vec2(0.0f, 1.0f); 2086 if (deFloatFloor(c.coords[1] + 1.0f) != deFloatFloor(1.1f)) 2087 c.color.z() = 1.0f; 2088 }); 2089} 2090 2091class ShaderStructTests : public tcu::TestCaseGroup 2092{ 2093public: 2094 ShaderStructTests (tcu::TestContext& context); 2095 virtual ~ShaderStructTests (void); 2096 2097 virtual void init (void); 2098 2099private: 2100 ShaderStructTests (const ShaderStructTests&); // not allowed! 2101 ShaderStructTests& operator= (const ShaderStructTests&); // not allowed! 2102}; 2103 2104ShaderStructTests::ShaderStructTests (tcu::TestContext& testCtx) 2105 : TestCaseGroup(testCtx, "struct", "Struct Tests") 2106{ 2107} 2108 2109ShaderStructTests::~ShaderStructTests (void) 2110{ 2111} 2112 2113void ShaderStructTests::init (void) 2114{ 2115 addChild(new LocalStructTests(m_testCtx)); 2116 addChild(new UniformStructTests(m_testCtx)); 2117} 2118 2119} // anonymous 2120 2121tcu::TestCaseGroup* createStructTests (tcu::TestContext& testCtx) 2122{ 2123 return new ShaderStructTests(testCtx); 2124} 2125 2126} // sr 2127} // vkt 2128