• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2022 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 "source/diff/diff.h"
16 
17 #include "diff_test_utils.h"
18 
19 #include "source/opt/build_module.h"
20 #include "source/opt/ir_context.h"
21 #include "source/spirv_constant.h"
22 #include "spirv-tools/libspirv.hpp"
23 #include "tools/util/cli_consumer.h"
24 
25 #include <fstream>
26 #include <string>
27 
28 #include "gtest/gtest.h"
29 
30 namespace spvtools {
31 namespace diff {
32 namespace {
33 
34 constexpr auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_6;
35 
Assemble(const std::string & spirv)36 std::unique_ptr<spvtools::opt::IRContext> Assemble(const std::string& spirv) {
37   spvtools::SpirvTools t(kDefaultEnvironment);
38   t.SetMessageConsumer(spvtools::utils::CLIMessageConsumer);
39   std::vector<uint32_t> binary;
40   if (!t.Assemble(spirv, &binary,
41                   spvtools::SpirvTools::kDefaultAssembleOption |
42                       SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS))
43     return nullptr;
44   return spvtools::BuildModule(kDefaultEnvironment,
45                                spvtools::utils::CLIMessageConsumer,
46                                binary.data(), binary.size());
47 }
48 
TEST(DiffIndentTest,Diff)49 TEST(DiffIndentTest, Diff) {
50   const std::string src = R"(OpCapability Shader
51     %ext_inst = OpExtInstImport "GLSL.std.450"
52     OpMemoryModel Logical GLSL450
53     OpEntryPoint Fragment %main "main"
54     OpExecutionMode %main OriginUpperLeft
55     %void = OpTypeVoid
56     %func = OpTypeFunction %void
57 
58     %main = OpFunction %void None %func
59     %main_entry = OpLabel
60     OpReturn
61     OpFunctionEnd;)";
62 
63   const std::string dst = R"(OpCapability Shader
64     OpMemoryModel Logical GLSL450
65     OpEntryPoint Fragment %main "main"
66     OpExecutionMode %main OriginUpperLeft
67     %void = OpTypeVoid
68     %func = OpTypeFunction %void
69 
70     %main = OpFunction %void None %func
71     %main_entry = OpLabel
72     OpReturn
73     OpFunctionEnd;)";
74 
75   const std::string diff = R"( ; SPIR-V
76  ; Version: 1.6
77  ; Generator: Khronos SPIR-V Tools Assembler; 0
78  ; Bound: 6
79  ; Schema: 0
80                 OpCapability Shader
81 -          %1 = OpExtInstImport "GLSL.std.450"
82                 OpMemoryModel Logical GLSL450
83                 OpEntryPoint Fragment %2 "main"
84                 OpExecutionMode %2 OriginUpperLeft
85            %3 = OpTypeVoid
86            %4 = OpTypeFunction %3
87            %2 = OpFunction %3 None %4
88            %5 = OpLabel
89                 OpReturn
90                 OpFunctionEnd
91 )";
92 
93   Options options;
94   options.indent = true;
95   DoStringDiffTest(src, dst, diff, options);
96 }
97 
TEST(DiffNoHeaderTest,Diff)98 TEST(DiffNoHeaderTest, Diff) {
99   const std::string src = R"(OpCapability Shader
100     %ext_inst = OpExtInstImport "GLSL.std.450"
101     OpMemoryModel Logical GLSL450
102     OpEntryPoint Fragment %main "main"
103     OpExecutionMode %main OriginUpperLeft
104     %void = OpTypeVoid
105     %func = OpTypeFunction %void
106 
107     %main = OpFunction %void None %func
108     %main_entry = OpLabel
109     OpReturn
110     OpFunctionEnd;)";
111 
112   const std::string dst = R"(OpCapability Shader
113     OpMemoryModel Logical GLSL450
114     OpEntryPoint Fragment %main "main"
115     OpExecutionMode %main OriginUpperLeft
116     %void = OpTypeVoid
117     %func = OpTypeFunction %void
118 
119     %main = OpFunction %void None %func
120     %main_entry = OpLabel
121     OpReturn
122     OpFunctionEnd;)";
123 
124   const std::string diff = R"( OpCapability Shader
125 -%1 = OpExtInstImport "GLSL.std.450"
126  OpMemoryModel Logical GLSL450
127  OpEntryPoint Fragment %2 "main"
128  OpExecutionMode %2 OriginUpperLeft
129  %3 = OpTypeVoid
130  %4 = OpTypeFunction %3
131  %2 = OpFunction %3 None %4
132  %5 = OpLabel
133  OpReturn
134  OpFunctionEnd
135 )";
136 
137   Options options;
138   options.no_header = true;
139   DoStringDiffTest(src, dst, diff, options);
140 }
141 
TEST(DiffHeaderTest,Diff)142 TEST(DiffHeaderTest, Diff) {
143   const std::string src_spirv = R"(OpCapability Shader
144     %ext_inst = OpExtInstImport "GLSL.std.450"
145     OpMemoryModel Logical GLSL450
146     OpEntryPoint Fragment %main "main"
147     OpExecutionMode %main OriginUpperLeft
148     %void = OpTypeVoid
149     %func = OpTypeFunction %void
150 
151     %main = OpFunction %void None %func
152     %main_entry = OpLabel
153     OpReturn
154     OpFunctionEnd;)";
155 
156   const std::string dst_spirv = R"(OpCapability Shader
157     OpMemoryModel Logical GLSL450
158     OpEntryPoint Fragment %main "main"
159     OpExecutionMode %main OriginUpperLeft
160     %void = OpTypeVoid
161     %func = OpTypeFunction %void
162 
163     %main = OpFunction %void None %func
164     %main_entry = OpLabel
165     OpReturn
166     OpFunctionEnd;)";
167 
168   const std::string diff = R"( ; SPIR-V
169 -; Version: 1.3
170 +; Version: 1.2
171 -; Generator: Khronos SPIR-V Tools Assembler; 3
172 +; Generator: Khronos Glslang Reference Front End; 10
173  ; Bound: 6
174  ; Schema: 0
175  OpCapability Shader
176 -%1 = OpExtInstImport "GLSL.std.450"
177  OpMemoryModel Logical GLSL450
178  OpEntryPoint Fragment %2 "main"
179  OpExecutionMode %2 OriginUpperLeft
180  %3 = OpTypeVoid
181  %4 = OpTypeFunction %3
182  %2 = OpFunction %3 None %4
183  %5 = OpLabel
184  OpReturn
185  OpFunctionEnd
186 )";
187 
188   // Load the src and dst modules
189   std::unique_ptr<spvtools::opt::IRContext> src = Assemble(src_spirv);
190   ASSERT_TRUE(src);
191 
192   std::unique_ptr<spvtools::opt::IRContext> dst = Assemble(dst_spirv);
193   ASSERT_TRUE(dst);
194 
195   // Differentiate them in the header.
196   const spvtools::opt::ModuleHeader src_header = {
197       spv::MagicNumber,
198       SPV_SPIRV_VERSION_WORD(1, 3),
199       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 3),
200       src->module()->IdBound(),
201       src->module()->schema(),
202   };
203   const spvtools::opt::ModuleHeader dst_header = {
204       spv::MagicNumber,
205       SPV_SPIRV_VERSION_WORD(1, 2),
206       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_GLSLANG, 10),
207       dst->module()->IdBound(),
208       dst->module()->schema(),
209   };
210 
211   src->module()->SetHeader(src_header);
212   dst->module()->SetHeader(dst_header);
213 
214   // Take the diff
215   Options options;
216   std::ostringstream diff_result;
217   spv_result_t result =
218       spvtools::diff::Diff(src.get(), dst.get(), diff_result, options);
219   ASSERT_EQ(result, SPV_SUCCESS);
220 
221   // Expect they match
222   EXPECT_EQ(diff_result.str(), diff);
223 }
224 
225 }  // namespace
226 }  // namespace diff
227 }  // namespace spvtools
228