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