Home | History | Annotate | Download | only in opt
      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