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.
PreambleAssembly()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
TypesAndFunctionsAssembly()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
TEST_P(FlattenDecorationTest,TransformsDecorations)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_SUITE_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_SUITE_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_SUITE_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_SUITE_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