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 #include <vector>
     18 
     19 #include "gmock/gmock.h"
     20 #include "test/opt/pass_fixture.h"
     21 #include "test/opt/pass_utils.h"
     22 
     23 namespace spvtools {
     24 namespace opt {
     25 namespace {
     26 
     27 // Returns the initial part of the assembly text for a valid
     28 // SPIR-V module, including instructions prior to decorations.
     29 std::string PreambleAssembly() {
     30   return
     31       R"(OpCapability Shader
     32 OpMemoryModel Logical GLSL450
     33 OpEntryPoint Fragment %main "main" %hue %saturation %value
     34 OpExecutionMode %main OriginUpperLeft
     35 OpName %main "main"
     36 OpName %void_fn "void_fn"
     37 OpName %hue "hue"
     38 OpName %saturation "saturation"
     39 OpName %value "value"
     40 OpName %entry "entry"
     41 OpName %Point "Point"
     42 OpName %Camera "Camera"
     43 )";
     44 }
     45 
     46 // Retuns types
     47 std::string TypesAndFunctionsAssembly() {
     48   return
     49       R"(%void = OpTypeVoid
     50 %void_fn = OpTypeFunction %void
     51 %float = OpTypeFloat 32
     52 %Point = OpTypeStruct %float %float %float
     53 %Camera = OpTypeStruct %float %float
     54 %_ptr_Input_float = OpTypePointer Input %float
     55 %hue = OpVariable %_ptr_Input_float Input
     56 %saturation = OpVariable %_ptr_Input_float Input
     57 %value = OpVariable %_ptr_Input_float Input
     58 %main = OpFunction %void None %void_fn
     59 %entry = OpLabel
     60 OpReturn
     61 OpFunctionEnd
     62 )";
     63 }
     64 
     65 struct FlattenDecorationCase {
     66   // Names and decorations before the pass.
     67   std::string input;
     68   // Names and decorations after the pass.
     69   std::string expected;
     70 };
     71 
     72 using FlattenDecorationTest =
     73     PassTest<::testing::TestWithParam<FlattenDecorationCase>>;
     74 
     75 TEST_P(FlattenDecorationTest, TransformsDecorations) {
     76   const auto before =
     77       PreambleAssembly() + GetParam().input + TypesAndFunctionsAssembly();
     78   const auto after =
     79       PreambleAssembly() + GetParam().expected + TypesAndFunctionsAssembly();
     80 
     81   SinglePassRunAndCheck<FlattenDecorationPass>(before, after, false, true);
     82 }
     83 
     84 INSTANTIATE_TEST_CASE_P(NoUses, FlattenDecorationTest,
     85                         ::testing::ValuesIn(std::vector<FlattenDecorationCase>{
     86                             // No OpDecorationGroup
     87                             {"", ""},
     88 
     89                             // OpDecorationGroup without any uses, and
     90                             // no OpName.
     91                             {"%group = OpDecorationGroup\n", ""},
     92 
     93                             // OpDecorationGroup without any uses, and
     94                             // with OpName targeting it. Proves you must
     95                             // remove the names as well.
     96                             {"OpName %group \"group\"\n"
     97                              "%group = OpDecorationGroup\n",
     98                              ""},
     99 
    100                             // OpDecorationGroup with decorations that
    101                             // target it, but no uses in OpGroupDecorate
    102                             // or OpGroupMemberDecorate instructions.
    103                             {"OpDecorate %group Flat\n"
    104                              "OpDecorate %group NoPerspective\n"
    105                              "%group = OpDecorationGroup\n",
    106                              ""},
    107                         }), );
    108 
    109 INSTANTIATE_TEST_CASE_P(OpGroupDecorate, FlattenDecorationTest,
    110                         ::testing::ValuesIn(std::vector<FlattenDecorationCase>{
    111                             // One OpGroupDecorate
    112                             {"OpName %group \"group\"\n"
    113                              "OpDecorate %group Flat\n"
    114                              "OpDecorate %group NoPerspective\n"
    115                              "%group = OpDecorationGroup\n"
    116                              "OpGroupDecorate %group %hue %saturation\n",
    117                              "OpDecorate %hue Flat\n"
    118                              "OpDecorate %saturation Flat\n"
    119                              "OpDecorate %hue NoPerspective\n"
    120                              "OpDecorate %saturation NoPerspective\n"},
    121                             // Multiple OpGroupDecorate
    122                             {"OpName %group \"group\"\n"
    123                              "OpDecorate %group Flat\n"
    124                              "OpDecorate %group NoPerspective\n"
    125                              "%group = OpDecorationGroup\n"
    126                              "OpGroupDecorate %group %hue %value\n"
    127                              "OpGroupDecorate %group %saturation\n",
    128                              "OpDecorate %hue Flat\n"
    129                              "OpDecorate %value Flat\n"
    130                              "OpDecorate %saturation Flat\n"
    131                              "OpDecorate %hue NoPerspective\n"
    132                              "OpDecorate %value NoPerspective\n"
    133                              "OpDecorate %saturation NoPerspective\n"},
    134                             // Two group decorations, interleaved
    135                             {"OpName %group0 \"group0\"\n"
    136                              "OpName %group1 \"group1\"\n"
    137                              "OpDecorate %group0 Flat\n"
    138                              "OpDecorate %group1 NoPerspective\n"
    139                              "%group0 = OpDecorationGroup\n"
    140                              "%group1 = OpDecorationGroup\n"
    141                              "OpGroupDecorate %group0 %hue %value\n"
    142                              "OpGroupDecorate %group1 %saturation\n",
    143                              "OpDecorate %hue Flat\n"
    144                              "OpDecorate %value Flat\n"
    145                              "OpDecorate %saturation NoPerspective\n"},
    146                             // Decoration with operands
    147                             {"OpName %group \"group\"\n"
    148                              "OpDecorate %group Location 42\n"
    149                              "%group = OpDecorationGroup\n"
    150                              "OpGroupDecorate %group %hue %saturation\n",
    151                              "OpDecorate %hue Location 42\n"
    152                              "OpDecorate %saturation Location 42\n"},
    153                         }), );
    154 
    155 INSTANTIATE_TEST_CASE_P(OpGroupMemberDecorate, FlattenDecorationTest,
    156                         ::testing::ValuesIn(std::vector<FlattenDecorationCase>{
    157                             // One OpGroupMemberDecorate
    158                             {"OpName %group \"group\"\n"
    159                              "OpDecorate %group Flat\n"
    160                              "OpDecorate %group Offset 16\n"
    161                              "%group = OpDecorationGroup\n"
    162                              "OpGroupMemberDecorate %group %Point 1\n",
    163                              "OpMemberDecorate %Point 1 Flat\n"
    164                              "OpMemberDecorate %Point 1 Offset 16\n"},
    165                             // Multiple OpGroupMemberDecorate using the same
    166                             // decoration group.
    167                             {"OpName %group \"group\"\n"
    168                              "OpDecorate %group Flat\n"
    169                              "OpDecorate %group NoPerspective\n"
    170                              "OpDecorate %group Offset 8\n"
    171                              "%group = OpDecorationGroup\n"
    172                              "OpGroupMemberDecorate %group %Point 2\n"
    173                              "OpGroupMemberDecorate %group %Camera 1\n",
    174                              "OpMemberDecorate %Point 2 Flat\n"
    175                              "OpMemberDecorate %Camera 1 Flat\n"
    176                              "OpMemberDecorate %Point 2 NoPerspective\n"
    177                              "OpMemberDecorate %Camera 1 NoPerspective\n"
    178                              "OpMemberDecorate %Point 2 Offset 8\n"
    179                              "OpMemberDecorate %Camera 1 Offset 8\n"},
    180                             // Two groups of member decorations, interleaved.
    181                             // Decoration is with and without operands.
    182                             {"OpName %group0 \"group0\"\n"
    183                              "OpName %group1 \"group1\"\n"
    184                              "OpDecorate %group0 Flat\n"
    185                              "OpDecorate %group0 Offset 8\n"
    186                              "OpDecorate %group1 NoPerspective\n"
    187                              "OpDecorate %group1 Offset 16\n"
    188                              "%group0 = OpDecorationGroup\n"
    189                              "%group1 = OpDecorationGroup\n"
    190                              "OpGroupMemberDecorate %group0 %Point 0\n"
    191                              "OpGroupMemberDecorate %group1 %Point 2\n",
    192                              "OpMemberDecorate %Point 0 Flat\n"
    193                              "OpMemberDecorate %Point 0 Offset 8\n"
    194                              "OpMemberDecorate %Point 2 NoPerspective\n"
    195                              "OpMemberDecorate %Point 2 Offset 16\n"},
    196                         }), );
    197 
    198 INSTANTIATE_TEST_CASE_P(UnrelatedDecorations, FlattenDecorationTest,
    199                         ::testing::ValuesIn(std::vector<FlattenDecorationCase>{
    200                             // A non-group non-member decoration is untouched.
    201                             {"OpDecorate %hue Centroid\n"
    202                              "OpDecorate %saturation Flat\n",
    203                              "OpDecorate %hue Centroid\n"
    204                              "OpDecorate %saturation Flat\n"},
    205                             // A non-group member decoration is untouched.
    206                             {"OpMemberDecorate %Point 0 Offset 0\n"
    207                              "OpMemberDecorate %Point 1 Offset 4\n"
    208                              "OpMemberDecorate %Point 1 Flat\n",
    209                              "OpMemberDecorate %Point 0 Offset 0\n"
    210                              "OpMemberDecorate %Point 1 Offset 4\n"
    211                              "OpMemberDecorate %Point 1 Flat\n"},
    212                             // A non-group non-member decoration survives any
    213                             // replacement of group decorations.
    214                             {"OpName %group \"group\"\n"
    215                              "OpDecorate %group Flat\n"
    216                              "OpDecorate %hue Centroid\n"
    217                              "OpDecorate %group NoPerspective\n"
    218                              "%group = OpDecorationGroup\n"
    219                              "OpGroupDecorate %group %hue %saturation\n",
    220                              "OpDecorate %hue Flat\n"
    221                              "OpDecorate %saturation Flat\n"
    222                              "OpDecorate %hue Centroid\n"
    223                              "OpDecorate %hue NoPerspective\n"
    224                              "OpDecorate %saturation NoPerspective\n"},
    225                             // A non-group member decoration survives any
    226                             // replacement of group decorations.
    227                             {"OpDecorate %group Offset 0\n"
    228                              "OpDecorate %group Flat\n"
    229                              "OpMemberDecorate %Point 1 Offset 4\n"
    230                              "%group = OpDecorationGroup\n"
    231                              "OpGroupMemberDecorate %group %Point 0\n",
    232                              "OpMemberDecorate %Point 0 Offset 0\n"
    233                              "OpMemberDecorate %Point 0 Flat\n"
    234                              "OpMemberDecorate %Point 1 Offset 4\n"},
    235                         }), );
    236 
    237 }  // namespace
    238 }  // namespace opt
    239 }  // namespace spvtools
    240