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