1 // Copyright (c) 2017 Valve Corporation 2 // Copyright (c) 2017 LunarG Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #include <string> 17 18 #include "test/opt/pass_fixture.h" 19 #include "test/opt/pass_utils.h" 20 21 namespace spvtools { 22 namespace opt { 23 namespace { 24 25 using LocalAccessChainConvertTest = PassTest<::testing::Test>; 26 27 TEST_F(LocalAccessChainConvertTest, StructOfVecsOfFloatConverted) { 28 // #version 140 29 // 30 // in vec4 BaseColor; 31 // 32 // struct S_t { 33 // vec4 v0; 34 // vec4 v1; 35 // }; 36 // 37 // void main() 38 // { 39 // S_t s0; 40 // s0.v1 = BaseColor; 41 // gl_FragColor = s0.v1; 42 // } 43 44 const std::string predefs_before = 45 R"(OpCapability Shader 46 %1 = OpExtInstImport "GLSL.std.450" 47 OpMemoryModel Logical GLSL450 48 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 49 OpExecutionMode %main OriginUpperLeft 50 OpSource GLSL 140 51 OpName %main "main" 52 OpName %S_t "S_t" 53 OpMemberName %S_t 0 "v0" 54 OpMemberName %S_t 1 "v1" 55 OpName %s0 "s0" 56 OpName %BaseColor "BaseColor" 57 OpName %gl_FragColor "gl_FragColor" 58 %void = OpTypeVoid 59 %8 = OpTypeFunction %void 60 %float = OpTypeFloat 32 61 %v4float = OpTypeVector %float 4 62 %S_t = OpTypeStruct %v4float %v4float 63 %_ptr_Function_S_t = OpTypePointer Function %S_t 64 %int = OpTypeInt 32 1 65 %int_1 = OpConstant %int 1 66 %_ptr_Input_v4float = OpTypePointer Input %v4float 67 %BaseColor = OpVariable %_ptr_Input_v4float Input 68 %_ptr_Function_v4float = OpTypePointer Function %v4float 69 %_ptr_Output_v4float = OpTypePointer Output %v4float 70 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 71 )"; 72 73 const std::string before = 74 R"( 75 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor 76 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 77 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 78 ; CHECK: OpStore %s0 [[ex1]] 79 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 80 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 81 ; CHECK: OpStore %gl_FragColor [[ex2]] 82 %main = OpFunction %void None %8 83 %17 = OpLabel 84 %s0 = OpVariable %_ptr_Function_S_t Function 85 %18 = OpLoad %v4float %BaseColor 86 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 87 OpStore %19 %18 88 %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 89 %21 = OpLoad %v4float %20 90 OpStore %gl_FragColor %21 91 OpReturn 92 OpFunctionEnd 93 )"; 94 95 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before, 96 true); 97 } 98 99 TEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) { 100 // #version 140 101 // 102 // in vec4 BaseColor; 103 // 104 // struct S_t { 105 // vec4 v0; 106 // vec4 v1; 107 // }; 108 // 109 // void main() 110 // { 111 // S_t s0; 112 // s0.v1 = BaseColor; 113 // gl_FragColor = s0.v1; 114 // } 115 116 const std::string predefs_before = 117 R"(OpCapability Shader 118 %1 = OpExtInstImport "GLSL.std.450" 119 OpMemoryModel Logical GLSL450 120 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 121 OpExecutionMode %main OriginUpperLeft 122 OpSource GLSL 140 123 OpName %main "main" 124 OpName %S_t "S_t" 125 OpMemberName %S_t 0 "v0" 126 OpMemberName %S_t 1 "v1" 127 OpName %s0 "s0" 128 OpName %BaseColor "BaseColor" 129 OpName %gl_FragColor "gl_FragColor" 130 %void = OpTypeVoid 131 %8 = OpTypeFunction %void 132 %float = OpTypeFloat 32 133 %v4float = OpTypeVector %float 4 134 %S_t = OpTypeStruct %v4float %v4float 135 %_ptr_Function_S_t = OpTypePointer Function %S_t 136 %int = OpTypeInt 32 1 137 %int_1 = OpConstant %int 1 138 %_ptr_Input_v4float = OpTypePointer Input %v4float 139 %BaseColor = OpVariable %_ptr_Input_v4float Input 140 %_ptr_Function_v4float = OpTypePointer Function %v4float 141 %_ptr_Output_v4float = OpTypePointer Output %v4float 142 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 143 )"; 144 145 const std::string before = 146 R"( 147 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor 148 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 149 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 150 ; CHECK: OpStore %s0 [[ex1]] 151 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 152 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 153 ; CHECK: OpStore %gl_FragColor [[ex2]] 154 %main = OpFunction %void None %8 155 %17 = OpLabel 156 %s0 = OpVariable %_ptr_Function_S_t Function 157 %18 = OpLoad %v4float %BaseColor 158 %19 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1 159 OpStore %19 %18 160 %20 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1 161 %21 = OpLoad %v4float %20 162 OpStore %gl_FragColor %21 163 OpReturn 164 OpFunctionEnd 165 )"; 166 167 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before, 168 true); 169 } 170 171 TEST_F(LocalAccessChainConvertTest, TwoUsesofSingleChainConverted) { 172 // #version 140 173 // 174 // in vec4 BaseColor; 175 // 176 // struct S_t { 177 // vec4 v0; 178 // vec4 v1; 179 // }; 180 // 181 // void main() 182 // { 183 // S_t s0; 184 // s0.v1 = BaseColor; 185 // gl_FragColor = s0.v1; 186 // } 187 188 const std::string predefs_before = 189 R"(OpCapability Shader 190 %1 = OpExtInstImport "GLSL.std.450" 191 OpMemoryModel Logical GLSL450 192 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 193 OpExecutionMode %main OriginUpperLeft 194 OpSource GLSL 140 195 OpName %main "main" 196 OpName %S_t "S_t" 197 OpMemberName %S_t 0 "v0" 198 OpMemberName %S_t 1 "v1" 199 OpName %s0 "s0" 200 OpName %BaseColor "BaseColor" 201 OpName %gl_FragColor "gl_FragColor" 202 %void = OpTypeVoid 203 %8 = OpTypeFunction %void 204 %float = OpTypeFloat 32 205 %v4float = OpTypeVector %float 4 206 %S_t = OpTypeStruct %v4float %v4float 207 %_ptr_Function_S_t = OpTypePointer Function %S_t 208 %int = OpTypeInt 32 1 209 %int_1 = OpConstant %int 1 210 %_ptr_Input_v4float = OpTypePointer Input %v4float 211 %BaseColor = OpVariable %_ptr_Input_v4float Input 212 %_ptr_Function_v4float = OpTypePointer Function %v4float 213 %_ptr_Output_v4float = OpTypePointer Output %v4float 214 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 215 )"; 216 217 const std::string before = 218 R"( 219 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor 220 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 221 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 222 ; CHECK: OpStore %s0 [[ex1]] 223 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 224 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 225 ; CHECK: OpStore %gl_FragColor [[ex2]] 226 %main = OpFunction %void None %8 227 %17 = OpLabel 228 %s0 = OpVariable %_ptr_Function_S_t Function 229 %18 = OpLoad %v4float %BaseColor 230 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 231 OpStore %19 %18 232 %20 = OpLoad %v4float %19 233 OpStore %gl_FragColor %20 234 OpReturn 235 OpFunctionEnd 236 )"; 237 238 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before, 239 true); 240 } 241 242 TEST_F(LocalAccessChainConvertTest, OpaqueConverted) { 243 // SPIR-V not representable in GLSL; not generatable from HLSL 244 // at the moment 245 246 const std::string predefs = 247 R"( 248 OpCapability Shader 249 %1 = OpExtInstImport "GLSL.std.450" 250 OpMemoryModel Logical GLSL450 251 OpEntryPoint Fragment %main "main" %outColor %texCoords 252 OpExecutionMode %main OriginUpperLeft 253 OpSource GLSL 140 254 OpName %main "main" 255 OpName %S_t "S_t" 256 OpMemberName %S_t 0 "v0" 257 OpMemberName %S_t 1 "v1" 258 OpMemberName %S_t 2 "smp" 259 OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;" 260 OpName %s "s" 261 OpName %outColor "outColor" 262 OpName %sampler15 "sampler15" 263 OpName %s0 "s0" 264 OpName %texCoords "texCoords" 265 OpName %param "param" 266 OpDecorate %sampler15 DescriptorSet 0 267 %void = OpTypeVoid 268 %12 = OpTypeFunction %void 269 %float = OpTypeFloat 32 270 %v2float = OpTypeVector %float 2 271 %v4float = OpTypeVector %float 4 272 %_ptr_Output_v4float = OpTypePointer Output %v4float 273 %outColor = OpVariable %_ptr_Output_v4float Output 274 %17 = OpTypeImage %float 2D 0 0 0 1 Unknown 275 %18 = OpTypeSampledImage %17 276 %S_t = OpTypeStruct %v2float %v2float %18 277 %_ptr_Function_S_t = OpTypePointer Function %S_t 278 %20 = OpTypeFunction %void %_ptr_Function_S_t 279 %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18 280 %_ptr_Function_18 = OpTypePointer Function %18 281 %sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant 282 %int = OpTypeInt 32 1 283 %int_0 = OpConstant %int 0 284 %int_2 = OpConstant %int 2 285 %_ptr_Function_v2float = OpTypePointer Function %v2float 286 %_ptr_Input_v2float = OpTypePointer Input %v2float 287 %texCoords = OpVariable %_ptr_Input_v2float Input 288 )"; 289 290 const std::string before = 291 R"( 292 ; CHECK: [[l1:%\w+]] = OpLoad %S_t %param 293 ; CHECK: [[e1:%\w+]] = OpCompositeExtract {{%\w+}} [[l1]] 2 294 ; CHECK: [[l2:%\w+]] = OpLoad %S_t %param 295 ; CHECK: [[e2:%\w+]] = OpCompositeExtract {{%\w+}} [[l2]] 0 296 ; CHECK: OpImageSampleImplicitLod {{%\w+}} [[e1]] [[e2]] 297 %main = OpFunction %void None %12 298 %28 = OpLabel 299 %s0 = OpVariable %_ptr_Function_S_t Function 300 %param = OpVariable %_ptr_Function_S_t Function 301 %29 = OpLoad %v2float %texCoords 302 %30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0 303 OpStore %30 %29 304 %31 = OpLoad %18 %sampler15 305 %32 = OpAccessChain %_ptr_Function_18 %s0 %int_2 306 OpStore %32 %31 307 %33 = OpLoad %S_t %s0 308 OpStore %param %33 309 %34 = OpAccessChain %_ptr_Function_18 %param %int_2 310 %35 = OpLoad %18 %34 311 %36 = OpAccessChain %_ptr_Function_v2float %param %int_0 312 %37 = OpLoad %v2float %36 313 %38 = OpImageSampleImplicitLod %v4float %35 %37 314 OpStore %outColor %38 315 OpReturn 316 OpFunctionEnd 317 )"; 318 319 const std::string remain = 320 R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20 321 %s = OpFunctionParameter %_ptr_Function_S_t 322 %39 = OpLabel 323 %40 = OpAccessChain %_ptr_Function_18 %s %int_2 324 %41 = OpLoad %18 %40 325 %42 = OpAccessChain %_ptr_Function_v2float %s %int_0 326 %43 = OpLoad %v2float %42 327 %44 = OpImageSampleImplicitLod %v4float %41 %43 328 OpStore %outColor %44 329 OpReturn 330 OpFunctionEnd 331 )"; 332 333 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before + remain, 334 true); 335 } 336 337 TEST_F(LocalAccessChainConvertTest, NestedStructsConverted) { 338 // #version 140 339 // 340 // in vec4 BaseColor; 341 // 342 // struct S1_t { 343 // vec4 v1; 344 // }; 345 // 346 // struct S2_t { 347 // vec4 v2; 348 // S1_t s1; 349 // }; 350 // 351 // void main() 352 // { 353 // S2_t s2; 354 // s2.s1.v1 = BaseColor; 355 // gl_FragColor = s2.s1.v1; 356 // } 357 358 const std::string predefs_before = 359 R"(OpCapability Shader 360 %1 = OpExtInstImport "GLSL.std.450" 361 OpMemoryModel Logical GLSL450 362 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 363 OpExecutionMode %main OriginUpperLeft 364 OpSource GLSL 140 365 OpName %main "main" 366 OpName %S1_t "S1_t" 367 OpMemberName %S1_t 0 "v1" 368 OpName %S2_t "S2_t" 369 OpMemberName %S2_t 0 "v2" 370 OpMemberName %S2_t 1 "s1" 371 OpName %s2 "s2" 372 OpName %BaseColor "BaseColor" 373 OpName %gl_FragColor "gl_FragColor" 374 %void = OpTypeVoid 375 %9 = OpTypeFunction %void 376 %float = OpTypeFloat 32 377 %v4float = OpTypeVector %float 4 378 %S1_t = OpTypeStruct %v4float 379 %S2_t = OpTypeStruct %v4float %S1_t 380 %_ptr_Function_S2_t = OpTypePointer Function %S2_t 381 %int = OpTypeInt 32 1 382 %int_1 = OpConstant %int 1 383 %int_0 = OpConstant %int 0 384 %_ptr_Input_v4float = OpTypePointer Input %v4float 385 %BaseColor = OpVariable %_ptr_Input_v4float Input 386 %_ptr_Function_v4float = OpTypePointer Function %v4float 387 %_ptr_Output_v4float = OpTypePointer Output %v4float 388 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 389 )"; 390 391 const std::string before = 392 R"( 393 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor 394 ; CHECK: [[ld1:%\w+]] = OpLoad %S2_t %s2 395 ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S2_t [[st_id]] [[ld1]] 1 0 396 ; CHECK: OpStore %s2 [[ex1]] 397 ; CHECK: [[ld2:%\w+]] = OpLoad %S2_t %s2 398 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 0 399 ; CHECK: OpStore %gl_FragColor [[ex2]] 400 %main = OpFunction %void None %9 401 %19 = OpLabel 402 %s2 = OpVariable %_ptr_Function_S2_t Function 403 %20 = OpLoad %v4float %BaseColor 404 %21 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0 405 OpStore %21 %20 406 %22 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0 407 %23 = OpLoad %v4float %22 408 OpStore %gl_FragColor %23 409 OpReturn 410 OpFunctionEnd 411 )"; 412 413 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before, 414 true); 415 } 416 417 TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) { 418 // Based on HLSL source code: 419 // struct S { 420 // float f; 421 // }; 422 423 // float main(float input : A) : B { 424 // S local = { input }; 425 // return local.f; 426 // } 427 428 const std::string predefs = R"(OpCapability Shader 429 OpMemoryModel Logical GLSL450 430 OpEntryPoint Vertex %main "main" %in_var_A %out_var_B 431 OpName %main "main" 432 OpName %in_var_A "in.var.A" 433 OpName %out_var_B "out.var.B" 434 OpName %S "S" 435 OpName %local "local" 436 %int = OpTypeInt 32 1 437 %void = OpTypeVoid 438 %8 = OpTypeFunction %void 439 %float = OpTypeFloat 32 440 %_ptr_Function_float = OpTypePointer Function %float 441 %_ptr_Input_float = OpTypePointer Input %float 442 %_ptr_Output_float = OpTypePointer Output %float 443 %S = OpTypeStruct %float 444 %_ptr_Function_S = OpTypePointer Function %S 445 %int_0 = OpConstant %int 0 446 %in_var_A = OpVariable %_ptr_Input_float Input 447 %out_var_B = OpVariable %_ptr_Output_float Output 448 %main = OpFunction %void None %8 449 %15 = OpLabel 450 %local = OpVariable %_ptr_Function_S Function 451 %16 = OpLoad %float %in_var_A 452 %17 = OpCompositeConstruct %S %16 453 OpStore %local %17 454 )"; 455 456 const std::string before = 457 R"( 458 ; CHECK: [[ld:%\w+]] = OpLoad %S %local 459 ; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0 460 ; CHECK: OpStore %out_var_B [[ex]] 461 %18 = OpAccessChain %_ptr_Function_float %local %int_0 462 %19 = OpAccessChain %_ptr_Function_float %local %int_0 463 %20 = OpLoad %float %18 464 OpStore %out_var_B %20 465 OpReturn 466 OpFunctionEnd 467 )"; 468 469 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before, true); 470 } 471 472 TEST_F(LocalAccessChainConvertTest, 473 StructOfVecsOfFloatConvertedWithDecorationOnLoad) { 474 // #version 140 475 // 476 // in vec4 BaseColor; 477 // 478 // struct S_t { 479 // vec4 v0; 480 // vec4 v1; 481 // }; 482 // 483 // void main() 484 // { 485 // S_t s0; 486 // s0.v1 = BaseColor; 487 // gl_FragColor = s0.v1; 488 // } 489 490 const std::string predefs_before = 491 R"(OpCapability Shader 492 %1 = OpExtInstImport "GLSL.std.450" 493 OpMemoryModel Logical GLSL450 494 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 495 OpExecutionMode %main OriginUpperLeft 496 OpSource GLSL 140 497 OpName %main "main" 498 OpName %S_t "S_t" 499 OpMemberName %S_t 0 "v0" 500 OpMemberName %S_t 1 "v1" 501 OpName %s0 "s0" 502 OpName %BaseColor "BaseColor" 503 OpName %gl_FragColor "gl_FragColor" 504 OpDecorate %21 RelaxedPrecision 505 %void = OpTypeVoid 506 %8 = OpTypeFunction %void 507 %float = OpTypeFloat 32 508 %v4float = OpTypeVector %float 4 509 %S_t = OpTypeStruct %v4float %v4float 510 %_ptr_Function_S_t = OpTypePointer Function %S_t 511 %int = OpTypeInt 32 1 512 %int_1 = OpConstant %int 1 513 %_ptr_Input_v4float = OpTypePointer Input %v4float 514 %BaseColor = OpVariable %_ptr_Input_v4float Input 515 %_ptr_Function_v4float = OpTypePointer Function %v4float 516 %_ptr_Output_v4float = OpTypePointer Output %v4float 517 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 518 )"; 519 520 const std::string before = 521 R"( 522 ; CHECK: OpDecorate 523 ; CHECK: OpDecorate [[ld2:%\w+]] RelaxedPrecision 524 ; CHECK-NOT: OpDecorate 525 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor 526 ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0 527 ; CHECK: [[ins:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 528 ; CHECK: OpStore %s0 [[ins]] 529 ; CHECK: [[ld2]] = OpLoad %S_t %s0 530 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 531 ; CHECK: OpStore %gl_FragColor [[ex2]] 532 %main = OpFunction %void None %8 533 %17 = OpLabel 534 %s0 = OpVariable %_ptr_Function_S_t Function 535 %18 = OpLoad %v4float %BaseColor 536 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 537 OpStore %19 %18 538 %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 539 %21 = OpLoad %v4float %20 540 OpStore %gl_FragColor %21 541 OpReturn 542 OpFunctionEnd 543 )"; 544 545 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before, 546 true); 547 } 548 549 TEST_F(LocalAccessChainConvertTest, 550 StructOfVecsOfFloatConvertedWithDecorationOnStore) { 551 // #version 140 552 // 553 // in vec4 BaseColor; 554 // 555 // struct S_t { 556 // vec4 v0; 557 // vec4 v1; 558 // }; 559 // 560 // void main() 561 // { 562 // S_t s0; 563 // s0.v1 = BaseColor; 564 // gl_FragColor = s0.v1; 565 // } 566 567 const std::string predefs_before = 568 R"(OpCapability Shader 569 %1 = OpExtInstImport "GLSL.std.450" 570 OpMemoryModel Logical GLSL450 571 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 572 OpExecutionMode %main OriginUpperLeft 573 OpSource GLSL 140 574 OpName %main "main" 575 OpName %S_t "S_t" 576 OpMemberName %S_t 0 "v0" 577 OpMemberName %S_t 1 "v1" 578 OpName %s0 "s0" 579 OpName %BaseColor "BaseColor" 580 OpName %gl_FragColor "gl_FragColor" 581 OpDecorate %s0 RelaxedPrecision 582 %void = OpTypeVoid 583 %8 = OpTypeFunction %void 584 %float = OpTypeFloat 32 585 %v4float = OpTypeVector %float 4 586 %S_t = OpTypeStruct %v4float %v4float 587 %_ptr_Function_S_t = OpTypePointer Function %S_t 588 %int = OpTypeInt 32 1 589 %int_1 = OpConstant %int 1 590 %_ptr_Input_v4float = OpTypePointer Input %v4float 591 %BaseColor = OpVariable %_ptr_Input_v4float Input 592 %_ptr_Function_v4float = OpTypePointer Function %v4float 593 %_ptr_Output_v4float = OpTypePointer Output %v4float 594 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 595 )"; 596 597 const std::string before = 598 R"( 599 ; CHECK: OpDecorate 600 ; CHECK: OpDecorate [[ld1:%\w+]] RelaxedPrecision 601 ; CHECK: OpDecorate [[ins:%\w+]] RelaxedPrecision 602 ; CHECK-NOT: OpDecorate 603 ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor 604 ; CHECK: [[ld1]] = OpLoad %S_t %s0 605 ; CHECK: [[ins]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1 606 ; CHECK: OpStore %s0 [[ins]] 607 ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0 608 ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 609 ; CHECK: OpStore %gl_FragColor [[ex2]] 610 %main = OpFunction %void None %8 611 %17 = OpLabel 612 %s0 = OpVariable %_ptr_Function_S_t Function 613 %18 = OpLoad %v4float %BaseColor 614 %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 615 OpStore %19 %18 616 %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 617 %21 = OpLoad %v4float %20 618 OpStore %gl_FragColor %21 619 OpReturn 620 OpFunctionEnd 621 )"; 622 623 SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before, 624 true); 625 } 626 627 TEST_F(LocalAccessChainConvertTest, DynamicallyIndexedVarNotConverted) { 628 // #version 140 629 // 630 // in vec4 BaseColor; 631 // flat in int Idx; 632 // in float Bi; 633 // 634 // struct S_t { 635 // vec4 v0; 636 // vec4 v1; 637 // }; 638 // 639 // void main() 640 // { 641 // S_t s0; 642 // s0.v1 = BaseColor; 643 // s0.v1[Idx] = Bi; 644 // gl_FragColor = s0.v1; 645 // } 646 647 const std::string assembly = 648 R"(OpCapability Shader 649 %1 = OpExtInstImport "GLSL.std.450" 650 OpMemoryModel Logical GLSL450 651 OpEntryPoint Fragment %main "main" %BaseColor %Idx %Bi %gl_FragColor 652 OpExecutionMode %main OriginUpperLeft 653 OpSource GLSL 140 654 OpName %main "main" 655 OpName %S_t "S_t" 656 OpMemberName %S_t 0 "v0" 657 OpMemberName %S_t 1 "v1" 658 OpName %s0 "s0" 659 OpName %BaseColor "BaseColor" 660 OpName %Idx "Idx" 661 OpName %Bi "Bi" 662 OpName %gl_FragColor "gl_FragColor" 663 OpDecorate %Idx Flat 664 %void = OpTypeVoid 665 %10 = OpTypeFunction %void 666 %float = OpTypeFloat 32 667 %v4float = OpTypeVector %float 4 668 %S_t = OpTypeStruct %v4float %v4float 669 %_ptr_Function_S_t = OpTypePointer Function %S_t 670 %int = OpTypeInt 32 1 671 %int_1 = OpConstant %int 1 672 %_ptr_Input_v4float = OpTypePointer Input %v4float 673 %BaseColor = OpVariable %_ptr_Input_v4float Input 674 %_ptr_Function_v4float = OpTypePointer Function %v4float 675 %_ptr_Input_int = OpTypePointer Input %int 676 %Idx = OpVariable %_ptr_Input_int Input 677 %_ptr_Input_float = OpTypePointer Input %float 678 %Bi = OpVariable %_ptr_Input_float Input 679 %_ptr_Function_float = OpTypePointer Function %float 680 %_ptr_Output_v4float = OpTypePointer Output %v4float 681 %gl_FragColor = OpVariable %_ptr_Output_v4float Output 682 %main = OpFunction %void None %10 683 %22 = OpLabel 684 %s0 = OpVariable %_ptr_Function_S_t Function 685 %23 = OpLoad %v4float %BaseColor 686 %24 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 687 OpStore %24 %23 688 %25 = OpLoad %int %Idx 689 %26 = OpLoad %float %Bi 690 %27 = OpAccessChain %_ptr_Function_float %s0 %int_1 %25 691 OpStore %27 %26 692 %28 = OpAccessChain %_ptr_Function_v4float %s0 %int_1 693 %29 = OpLoad %v4float %28 694 OpStore %gl_FragColor %29 695 OpReturn 696 OpFunctionEnd 697 )"; 698 699 SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false, 700 true); 701 } 702 703 // TODO(greg-lunarg): Add tests to verify handling of these cases: 704 // 705 // Assorted vector and matrix types 706 // Assorted struct array types 707 // Assorted scalar types 708 // Assorted non-target types 709 // OpInBoundsAccessChain 710 // Others? 711 712 } // namespace 713 } // namespace opt 714 } // namespace spvtools 715