1 // Copyright (c) 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16
17 #include "gmock/gmock.h"
18 #include "spirv-tools/optimizer.hpp"
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 using StripNonSemanticInfoTest = PassTest<::testing::Test>;
27
28 // This test acts as an end-to-end code example on how to strip
29 // reflection info from a SPIR-V module. Use this code pattern
30 // when you have compiled HLSL code with Glslang or DXC using
31 // option -fhlsl_functionality1 to insert reflection information,
32 // but then want to filter out the extra instructions before sending
33 // it to a driver that does not implement VK_GOOGLE_hlsl_functionality1.
TEST_F(StripNonSemanticInfoTest,StripReflectEnd2EndExample)34 TEST_F(StripNonSemanticInfoTest, StripReflectEnd2EndExample) {
35 // This is a non-sensical example, but exercises the instructions.
36 std::string before = R"(OpCapability Shader
37 OpCapability Linkage
38 OpExtension "SPV_GOOGLE_decorate_string"
39 OpExtension "SPV_GOOGLE_hlsl_functionality1"
40 OpMemoryModel Logical Simple
41 OpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar"
42 OpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness"
43 %void = OpTypeVoid
44 %float = OpTypeFloat 32
45 )";
46 SpirvTools tools(SPV_ENV_UNIVERSAL_1_1);
47 std::vector<uint32_t> binary_in;
48 tools.Assemble(before, &binary_in);
49
50 // Instantiate the optimizer, and run the strip-nonsemantic-info
51 // pass over the |binary_in| module, and place the modified module
52 // into |binary_out|.
53 spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_1);
54 optimizer.RegisterPass(spvtools::CreateStripNonSemanticInfoPass());
55 std::vector<uint32_t> binary_out;
56 optimizer.Run(binary_in.data(), binary_in.size(), &binary_out);
57
58 // Check results
59 std::string disassembly;
60 tools.Disassemble(binary_out.data(), binary_out.size(), &disassembly);
61 std::string after = R"(OpCapability Shader
62 OpCapability Linkage
63 OpMemoryModel Logical Simple
64 %void = OpTypeVoid
65 %float = OpTypeFloat 32
66 )";
67 EXPECT_THAT(disassembly, testing::Eq(after));
68 }
69
70 // This test is functionally the same as the end-to-end test above,
71 // but uses the test SinglePassRunAndCheck test fixture instead.
TEST_F(StripNonSemanticInfoTest,StripHlslSemantic)72 TEST_F(StripNonSemanticInfoTest, StripHlslSemantic) {
73 // This is a non-sensical example, but exercises the instructions.
74 std::string before = R"(OpCapability Shader
75 OpCapability Linkage
76 OpExtension "SPV_GOOGLE_decorate_string"
77 OpExtension "SPV_GOOGLE_hlsl_functionality1"
78 OpMemoryModel Logical Simple
79 OpDecorateStringGOOGLE %float HlslSemanticGOOGLE "foobar"
80 OpDecorateStringGOOGLE %void HlslSemanticGOOGLE "my goodness"
81 %void = OpTypeVoid
82 %float = OpTypeFloat 32
83 )";
84 std::string after = R"(OpCapability Shader
85 OpCapability Linkage
86 OpMemoryModel Logical Simple
87 %void = OpTypeVoid
88 %float = OpTypeFloat 32
89 )";
90
91 SinglePassRunAndCheck<StripNonSemanticInfoPass>(before, after, false);
92 }
93
TEST_F(StripNonSemanticInfoTest,StripHlslCounterBuffer)94 TEST_F(StripNonSemanticInfoTest, StripHlslCounterBuffer) {
95 std::string before = R"(OpCapability Shader
96 OpCapability Linkage
97 OpExtension "SPV_GOOGLE_hlsl_functionality1"
98 OpMemoryModel Logical Simple
99 OpDecorateId %void HlslCounterBufferGOOGLE %float
100 %void = OpTypeVoid
101 %float = OpTypeFloat 32
102 )";
103 std::string after = R"(OpCapability Shader
104 OpCapability Linkage
105 OpMemoryModel Logical Simple
106 %void = OpTypeVoid
107 %float = OpTypeFloat 32
108 )";
109
110 SinglePassRunAndCheck<StripNonSemanticInfoPass>(before, after, false);
111 }
112
TEST_F(StripNonSemanticInfoTest,StripHlslSemanticOnMember)113 TEST_F(StripNonSemanticInfoTest, StripHlslSemanticOnMember) {
114 // This is a non-sensical example, but exercises the instructions.
115 std::string before = R"(OpCapability Shader
116 OpCapability Linkage
117 OpExtension "SPV_GOOGLE_decorate_string"
118 OpExtension "SPV_GOOGLE_hlsl_functionality1"
119 OpMemoryModel Logical Simple
120 OpMemberDecorateStringGOOGLE %struct 0 HlslSemanticGOOGLE "foobar"
121 %float = OpTypeFloat 32
122 %_struct_3 = OpTypeStruct %float
123 )";
124 std::string after = R"(OpCapability Shader
125 OpCapability Linkage
126 OpMemoryModel Logical Simple
127 %float = OpTypeFloat 32
128 %_struct_3 = OpTypeStruct %float
129 )";
130
131 SinglePassRunAndCheck<StripNonSemanticInfoPass>(before, after, false);
132 }
133
TEST_F(StripNonSemanticInfoTest,StripNonSemanticImport)134 TEST_F(StripNonSemanticInfoTest, StripNonSemanticImport) {
135 std::string text = R"(
136 ; CHECK-NOT: OpExtension "SPV_KHR_non_semantic_info"
137 ; CHECK-NOT: OpExtInstImport
138 OpCapability Shader
139 OpCapability Linkage
140 OpExtension "SPV_KHR_non_semantic_info"
141 %ext = OpExtInstImport "NonSemantic.Test"
142 OpMemoryModel Logical GLSL450
143 )";
144
145 SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true);
146 }
147
TEST_F(StripNonSemanticInfoTest,StripNonSemanticGlobal)148 TEST_F(StripNonSemanticInfoTest, StripNonSemanticGlobal) {
149 std::string text = R"(
150 ; CHECK-NOT: OpExtInst
151 OpCapability Shader
152 OpCapability Linkage
153 OpExtension "SPV_KHR_non_semantic_info"
154 %ext = OpExtInstImport "NonSemantic.Test"
155 OpMemoryModel Logical GLSL450
156 %void = OpTypeVoid
157 %1 = OpExtInst %void %ext 1
158 )";
159
160 SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true);
161 }
162
TEST_F(StripNonSemanticInfoTest,StripNonSemanticInFunction)163 TEST_F(StripNonSemanticInfoTest, StripNonSemanticInFunction) {
164 std::string text = R"(
165 ; CHECK-NOT: OpExtInst
166 OpCapability Shader
167 OpCapability Linkage
168 OpExtension "SPV_KHR_non_semantic_info"
169 %ext = OpExtInstImport "NonSemantic.Test"
170 OpMemoryModel Logical GLSL450
171 %void = OpTypeVoid
172 %void_fn = OpTypeFunction %void
173 %foo = OpFunction %void None %void_fn
174 %entry = OpLabel
175 %1 = OpExtInst %void %ext 1 %foo
176 OpReturn
177 OpFunctionEnd
178 )";
179
180 SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true);
181 }
182
TEST_F(StripNonSemanticInfoTest,StripNonSemanticAfterFunction)183 TEST_F(StripNonSemanticInfoTest, StripNonSemanticAfterFunction) {
184 std::string text = R"(
185 ; CHECK-NOT: OpExtInst
186 OpCapability Shader
187 OpCapability Linkage
188 OpExtension "SPV_KHR_non_semantic_info"
189 %ext = OpExtInstImport "NonSemantic.Test"
190 OpMemoryModel Logical GLSL450
191 %void = OpTypeVoid
192 %void_fn = OpTypeFunction %void
193 %foo = OpFunction %void None %void_fn
194 %entry = OpLabel
195 OpReturn
196 OpFunctionEnd
197 %1 = OpExtInst %void %ext 1 %foo
198 )";
199
200 SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true);
201 }
202
TEST_F(StripNonSemanticInfoTest,StripNonSemanticBetweenFunctions)203 TEST_F(StripNonSemanticInfoTest, StripNonSemanticBetweenFunctions) {
204 std::string text = R"(
205 ; CHECK-NOT: OpExtInst
206 OpCapability Shader
207 OpCapability Linkage
208 OpExtension "SPV_KHR_non_semantic_info"
209 %ext = OpExtInstImport "NonSemantic.Test"
210 OpMemoryModel Logical GLSL450
211 %void = OpTypeVoid
212 %void_fn = OpTypeFunction %void
213 %foo = OpFunction %void None %void_fn
214 %entry = OpLabel
215 OpReturn
216 OpFunctionEnd
217 %1 = OpExtInst %void %ext 1 %foo
218 %bar = OpFunction %void None %void_fn
219 %bar_entry = OpLabel
220 OpReturn
221 OpFunctionEnd
222 )";
223
224 SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true);
225 }
226
227 // Make sure that strip reflect does not remove the debug info (OpString and
228 // OpLine).
TEST_F(StripNonSemanticInfoTest,DontStripDebug)229 TEST_F(StripNonSemanticInfoTest, DontStripDebug) {
230 std::string text = R"(OpCapability Shader
231 OpMemoryModel Logical Simple
232 OpEntryPoint Fragment %1 "main"
233 OpExecutionMode %1 OriginUpperLeft
234 %2 = OpString "file"
235 %void = OpTypeVoid
236 %4 = OpTypeFunction %void
237 %1 = OpFunction %void None %4
238 %5 = OpLabel
239 OpLine %2 1 1
240 OpReturn
241 OpFunctionEnd
242 )";
243
244 SinglePassRunAndCheck<StripNonSemanticInfoPass>(text, text, false);
245 }
246
TEST_F(StripNonSemanticInfoTest,RemovedNonSemanticDebugInfo)247 TEST_F(StripNonSemanticInfoTest, RemovedNonSemanticDebugInfo) {
248 const std::string text = R"(
249 ;CHECK-NOT: OpExtension "SPV_KHR_non_semantic_info
250 ;CHECK-NOT: OpExtInstImport "NonSemantic.Shader.DebugInfo.100
251 ;CHECK-NOT: OpExtInst %void {{%\w+}} DebugSource
252 ;CHECK-NOT: OpExtInst %void {{%\w+}} DebugLine
253 OpCapability Shader
254 OpExtension "SPV_KHR_non_semantic_info"
255 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
256 OpMemoryModel Logical GLSL450
257 OpEntryPoint Fragment %PSMain "PSMain" %in_var_COLOR %out_var_SV_TARGET
258 OpExecutionMode %PSMain OriginUpperLeft
259 %5 = OpString "t.hlsl"
260 %6 = OpString "float"
261 %7 = OpString "color"
262 %8 = OpString "PSInput"
263 %9 = OpString "PSMain"
264 %10 = OpString ""
265 %11 = OpString "input"
266 OpName %in_var_COLOR "in.var.COLOR"
267 OpName %out_var_SV_TARGET "out.var.SV_TARGET"
268 OpName %PSMain "PSMain"
269 OpDecorate %in_var_COLOR Location 0
270 OpDecorate %out_var_SV_TARGET Location 0
271 %uint = OpTypeInt 32 0
272 %float = OpTypeFloat 32
273 %v4float = OpTypeVector %float 4
274 %_ptr_Input_v4float = OpTypePointer Input %v4float
275 %_ptr_Output_v4float = OpTypePointer Output %v4float
276 %void = OpTypeVoid
277 %uint_1 = OpConstant %uint 1
278 %uint_9 = OpConstant %uint 9
279 %21 = OpTypeFunction %void
280 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
281 %out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
282 %13 = OpExtInst %void %1 DebugSource %5
283 %PSMain = OpFunction %void None %21
284 %22 = OpLabel
285 %23 = OpLoad %v4float %in_var_COLOR
286 OpStore %out_var_SV_TARGET %23
287 %24 = OpExtInst %void %1 DebugLine %13 %uint_9 %uint_9 %uint_1 %uint_1
288 OpReturn
289 OpFunctionEnd
290 )";
291 SinglePassRunAndMatch<StripNonSemanticInfoPass>(text, true);
292 }
293
294 } // namespace
295 } // namespace opt
296 } // namespace spvtools
297