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