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