1 // Copyright (c) 2017 Pierre Moreau
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 <iostream>
16 #include <memory>
17 #include <string>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21 #include "source/opt/build_module.h"
22 #include "source/opt/ir_context.h"
23 #include "source/opt/pass_manager.h"
24 #include "source/opt/remove_duplicates_pass.h"
25 #include "source/spirv_constant.h"
26 #include "test/unit_spirv.h"
27
28 namespace spvtools {
29 namespace opt {
30 namespace {
31
32 class RemoveDuplicatesTest : public ::testing::Test {
33 public:
RemoveDuplicatesTest()34 RemoveDuplicatesTest()
35 : tools_(SPV_ENV_UNIVERSAL_1_2),
36 context_(),
37 consumer_([this](spv_message_level_t level, const char*,
38 const spv_position_t& position, const char* message) {
39 if (!error_message_.empty()) error_message_ += "\n";
40 switch (level) {
41 case SPV_MSG_FATAL:
42 case SPV_MSG_INTERNAL_ERROR:
43 case SPV_MSG_ERROR:
44 error_message_ += "ERROR";
45 break;
46 case SPV_MSG_WARNING:
47 error_message_ += "WARNING";
48 break;
49 case SPV_MSG_INFO:
50 error_message_ += "INFO";
51 break;
52 case SPV_MSG_DEBUG:
53 error_message_ += "DEBUG";
54 break;
55 }
56 error_message_ +=
57 ": " + std::to_string(position.index) + ": " + message;
58 }),
59 disassemble_options_(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER),
60 error_message_() {
61 tools_.SetMessageConsumer(consumer_);
62 }
63
TearDown()64 void TearDown() override { error_message_.clear(); }
65
RunPass(const std::string & text)66 std::string RunPass(const std::string& text) {
67 context_ = spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer_, text);
68 if (!context_.get()) return std::string();
69
70 PassManager manager;
71 manager.SetMessageConsumer(consumer_);
72 manager.AddPass<RemoveDuplicatesPass>();
73
74 Pass::Status pass_res = manager.Run(context_.get());
75 if (pass_res == Pass::Status::Failure) return std::string();
76
77 return ModuleToText();
78 }
79
80 // Disassembles |binary| and outputs the result in |text|. If |text| is a
81 // null pointer, SPV_ERROR_INVALID_POINTER is returned.
Disassemble(const std::vector<uint32_t> & binary,std::string * text)82 spv_result_t Disassemble(const std::vector<uint32_t>& binary,
83 std::string* text) {
84 if (!text) return SPV_ERROR_INVALID_POINTER;
85 return tools_.Disassemble(binary, text, disassemble_options_)
86 ? SPV_SUCCESS
87 : SPV_ERROR_INVALID_BINARY;
88 }
89
90 // Returns the accumulated error messages for the test.
GetErrorMessage() const91 std::string GetErrorMessage() const { return error_message_; }
92
ToText(const std::vector<Instruction * > & inst)93 std::string ToText(const std::vector<Instruction*>& inst) {
94 std::vector<uint32_t> binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u};
95 for (const Instruction* i : inst)
96 i->ToBinaryWithoutAttachedDebugInsts(&binary);
97 std::string text;
98 Disassemble(binary, &text);
99 return text;
100 }
101
ModuleToText()102 std::string ModuleToText() {
103 std::vector<uint32_t> binary;
104 context_->module()->ToBinary(&binary, false);
105 std::string text;
106 Disassemble(binary, &text);
107 return text;
108 }
109
110 private:
111 spvtools::SpirvTools
112 tools_; // An instance for calling SPIRV-Tools functionalities.
113 std::unique_ptr<IRContext> context_;
114 spvtools::MessageConsumer consumer_;
115 uint32_t disassemble_options_;
116 std::string error_message_;
117 };
118
TEST_F(RemoveDuplicatesTest,DuplicateCapabilities)119 TEST_F(RemoveDuplicatesTest, DuplicateCapabilities) {
120 const std::string spirv = R"(
121 OpCapability Shader
122 OpCapability Linkage
123 OpCapability Shader
124 OpMemoryModel Logical GLSL450
125 )";
126 const std::string after = R"(OpCapability Shader
127 OpCapability Linkage
128 OpMemoryModel Logical GLSL450
129 )";
130
131 EXPECT_EQ(RunPass(spirv), after);
132 EXPECT_EQ(GetErrorMessage(), "");
133 }
134
TEST_F(RemoveDuplicatesTest,DuplicateExtInstImports)135 TEST_F(RemoveDuplicatesTest, DuplicateExtInstImports) {
136 const std::string spirv = R"(
137 OpCapability Shader
138 OpCapability Linkage
139 %1 = OpExtInstImport "OpenCL.std"
140 %2 = OpExtInstImport "OpenCL.std"
141 %3 = OpExtInstImport "GLSL.std.450"
142 OpMemoryModel Logical GLSL450
143 )";
144 const std::string after = R"(OpCapability Shader
145 OpCapability Linkage
146 %1 = OpExtInstImport "OpenCL.std"
147 %3 = OpExtInstImport "GLSL.std.450"
148 OpMemoryModel Logical GLSL450
149 )";
150
151 EXPECT_EQ(RunPass(spirv), after);
152 EXPECT_EQ(GetErrorMessage(), "");
153 }
154
TEST_F(RemoveDuplicatesTest,DuplicateTypes)155 TEST_F(RemoveDuplicatesTest, DuplicateTypes) {
156 const std::string spirv = R"(
157 OpCapability Shader
158 OpCapability Linkage
159 OpMemoryModel Logical GLSL450
160 %1 = OpTypeInt 32 0
161 %2 = OpTypeInt 32 0
162 %3 = OpTypeStruct %1 %2
163 )";
164 const std::string after = R"(OpCapability Shader
165 OpCapability Linkage
166 OpMemoryModel Logical GLSL450
167 %1 = OpTypeInt 32 0
168 %3 = OpTypeStruct %1 %1
169 )";
170
171 EXPECT_EQ(RunPass(spirv), after);
172 EXPECT_EQ(GetErrorMessage(), "");
173 }
174
TEST_F(RemoveDuplicatesTest,SameTypeDifferentMemberDecoration)175 TEST_F(RemoveDuplicatesTest, SameTypeDifferentMemberDecoration) {
176 const std::string spirv = R"(
177 OpCapability Shader
178 OpCapability Linkage
179 OpMemoryModel Logical GLSL450
180 OpDecorate %1 GLSLPacked
181 %2 = OpTypeInt 32 0
182 %1 = OpTypeStruct %2 %2
183 %3 = OpTypeStruct %2 %2
184 )";
185 const std::string after = R"(OpCapability Shader
186 OpCapability Linkage
187 OpMemoryModel Logical GLSL450
188 OpDecorate %1 GLSLPacked
189 %2 = OpTypeInt 32 0
190 %1 = OpTypeStruct %2 %2
191 %3 = OpTypeStruct %2 %2
192 )";
193
194 EXPECT_EQ(RunPass(spirv), after);
195 EXPECT_EQ(GetErrorMessage(), "");
196 }
197
TEST_F(RemoveDuplicatesTest,SameTypeAndMemberDecoration)198 TEST_F(RemoveDuplicatesTest, SameTypeAndMemberDecoration) {
199 const std::string spirv = R"(
200 OpCapability Shader
201 OpCapability Linkage
202 OpMemoryModel Logical GLSL450
203 OpDecorate %1 GLSLPacked
204 OpDecorate %2 GLSLPacked
205 %3 = OpTypeInt 32 0
206 %1 = OpTypeStruct %3 %3
207 %2 = OpTypeStruct %3 %3
208 )";
209 const std::string after = R"(OpCapability Shader
210 OpCapability Linkage
211 OpMemoryModel Logical GLSL450
212 OpDecorate %1 GLSLPacked
213 %3 = OpTypeInt 32 0
214 %1 = OpTypeStruct %3 %3
215 )";
216
217 EXPECT_EQ(RunPass(spirv), after);
218 EXPECT_EQ(GetErrorMessage(), "");
219 }
220
TEST_F(RemoveDuplicatesTest,SameTypeAndDifferentName)221 TEST_F(RemoveDuplicatesTest, SameTypeAndDifferentName) {
222 const std::string spirv = R"(
223 OpCapability Shader
224 OpCapability Linkage
225 OpMemoryModel Logical GLSL450
226 OpName %1 "Type1"
227 OpName %2 "Type2"
228 %3 = OpTypeInt 32 0
229 %1 = OpTypeStruct %3 %3
230 %2 = OpTypeStruct %3 %3
231 )";
232 const std::string after = R"(OpCapability Shader
233 OpCapability Linkage
234 OpMemoryModel Logical GLSL450
235 OpName %1 "Type1"
236 %3 = OpTypeInt 32 0
237 %1 = OpTypeStruct %3 %3
238 )";
239
240 EXPECT_EQ(RunPass(spirv), after);
241 EXPECT_EQ(GetErrorMessage(), "");
242 }
243
244 // Check that #1033 has been fixed.
TEST_F(RemoveDuplicatesTest,DoNotRemoveDifferentOpDecorationGroup)245 TEST_F(RemoveDuplicatesTest, DoNotRemoveDifferentOpDecorationGroup) {
246 const std::string spirv = R"(
247 OpCapability Shader
248 OpCapability Linkage
249 OpMemoryModel Logical GLSL450
250 OpDecorate %1 Constant
251 %1 = OpDecorationGroup
252 OpDecorate %2 Restrict
253 %2 = OpDecorationGroup
254 OpGroupDecorate %3 %1 %2
255 %4 = OpTypeInt 32 0
256 %3 = OpVariable %4 Uniform
257 )";
258 const std::string after = R"(OpCapability Shader
259 OpCapability Linkage
260 OpMemoryModel Logical GLSL450
261 OpDecorate %1 Constant
262 %1 = OpDecorationGroup
263 OpDecorate %2 Restrict
264 %2 = OpDecorationGroup
265 OpGroupDecorate %3 %1 %2
266 %4 = OpTypeInt 32 0
267 %3 = OpVariable %4 Uniform
268 )";
269
270 EXPECT_EQ(RunPass(spirv), after);
271 EXPECT_EQ(GetErrorMessage(), "");
272 }
273
TEST_F(RemoveDuplicatesTest,DifferentDecorationGroup)274 TEST_F(RemoveDuplicatesTest, DifferentDecorationGroup) {
275 const std::string spirv = R"(
276 OpCapability Shader
277 OpCapability Linkage
278 OpMemoryModel Logical GLSL450
279 OpDecorate %1 Constant
280 OpDecorate %1 Restrict
281 %1 = OpDecorationGroup
282 OpDecorate %2 Constant
283 %2 = OpDecorationGroup
284 OpGroupDecorate %1 %3
285 OpGroupDecorate %2 %4
286 %5 = OpTypeInt 32 0
287 %3 = OpVariable %5 Uniform
288 %4 = OpVariable %5 Uniform
289 )";
290 const std::string after = R"(OpCapability Shader
291 OpCapability Linkage
292 OpMemoryModel Logical GLSL450
293 OpDecorate %1 Constant
294 OpDecorate %1 Restrict
295 %1 = OpDecorationGroup
296 OpDecorate %2 Constant
297 %2 = OpDecorationGroup
298 OpGroupDecorate %1 %3
299 OpGroupDecorate %2 %4
300 %5 = OpTypeInt 32 0
301 %3 = OpVariable %5 Uniform
302 %4 = OpVariable %5 Uniform
303 )";
304
305 EXPECT_EQ(RunPass(spirv), after);
306 EXPECT_EQ(GetErrorMessage(), "");
307 }
308
309 // Test what happens when a type is a resource type. For now we are merging
310 // them, but, if we want to merge types and make reflection work (issue #1372),
311 // we will not be able to merge %2 and %3 below.
TEST_F(RemoveDuplicatesTest,DontMergeNestedResourceTypes)312 TEST_F(RemoveDuplicatesTest, DontMergeNestedResourceTypes) {
313 const std::string spirv = R"(OpCapability Shader
314 OpMemoryModel Logical GLSL450
315 OpSource HLSL 600
316 OpName %1 "PositionAdjust"
317 OpMemberName %1 0 "XAdjust"
318 OpName %2 "NormalAdjust"
319 OpMemberName %2 0 "XDir"
320 OpMemberName %3 0 "AdjustXYZ"
321 OpMemberName %3 1 "AdjustDir"
322 OpName %4 "Constants"
323 OpMemberDecorate %1 0 Offset 0
324 OpMemberDecorate %2 0 Offset 0
325 OpMemberDecorate %3 0 Offset 0
326 OpMemberDecorate %3 1 Offset 16
327 OpDecorate %3 Block
328 OpDecorate %4 DescriptorSet 0
329 OpDecorate %4 Binding 0
330 %5 = OpTypeFloat 32
331 %6 = OpTypeVector %5 3
332 %1 = OpTypeStruct %6
333 %2 = OpTypeStruct %6
334 %3 = OpTypeStruct %1 %2
335 %7 = OpTypePointer Uniform %3
336 %4 = OpVariable %7 Uniform
337 )";
338
339 const std::string result = R"(OpCapability Shader
340 OpMemoryModel Logical GLSL450
341 OpSource HLSL 600
342 OpName %1 "PositionAdjust"
343 OpMemberName %1 0 "XAdjust"
344 OpMemberName %3 0 "AdjustXYZ"
345 OpMemberName %3 1 "AdjustDir"
346 OpName %4 "Constants"
347 OpMemberDecorate %1 0 Offset 0
348 OpMemberDecorate %3 0 Offset 0
349 OpMemberDecorate %3 1 Offset 16
350 OpDecorate %3 Block
351 OpDecorate %4 DescriptorSet 0
352 OpDecorate %4 Binding 0
353 %5 = OpTypeFloat 32
354 %6 = OpTypeVector %5 3
355 %1 = OpTypeStruct %6
356 %3 = OpTypeStruct %1 %1
357 %7 = OpTypePointer Uniform %3
358 %4 = OpVariable %7 Uniform
359 )";
360
361 EXPECT_EQ(RunPass(spirv), result);
362 EXPECT_EQ(GetErrorMessage(), "");
363 }
364
365 // See comment for DontMergeNestedResourceTypes.
TEST_F(RemoveDuplicatesTest,DontMergeResourceTypes)366 TEST_F(RemoveDuplicatesTest, DontMergeResourceTypes) {
367 const std::string spirv = R"(OpCapability Shader
368 OpMemoryModel Logical GLSL450
369 OpSource HLSL 600
370 OpName %1 "PositionAdjust"
371 OpMemberName %1 0 "XAdjust"
372 OpName %2 "NormalAdjust"
373 OpMemberName %2 0 "XDir"
374 OpName %3 "Constants"
375 OpMemberDecorate %1 0 Offset 0
376 OpMemberDecorate %2 0 Offset 0
377 OpDecorate %3 DescriptorSet 0
378 OpDecorate %3 Binding 0
379 OpDecorate %4 DescriptorSet 1
380 OpDecorate %4 Binding 0
381 %5 = OpTypeFloat 32
382 %6 = OpTypeVector %5 3
383 %1 = OpTypeStruct %6
384 %2 = OpTypeStruct %6
385 %7 = OpTypePointer Uniform %1
386 %8 = OpTypePointer Uniform %2
387 %3 = OpVariable %7 Uniform
388 %4 = OpVariable %8 Uniform
389 )";
390
391 const std::string result = R"(OpCapability Shader
392 OpMemoryModel Logical GLSL450
393 OpSource HLSL 600
394 OpName %1 "PositionAdjust"
395 OpMemberName %1 0 "XAdjust"
396 OpName %3 "Constants"
397 OpMemberDecorate %1 0 Offset 0
398 OpDecorate %3 DescriptorSet 0
399 OpDecorate %3 Binding 0
400 OpDecorate %4 DescriptorSet 1
401 OpDecorate %4 Binding 0
402 %5 = OpTypeFloat 32
403 %6 = OpTypeVector %5 3
404 %1 = OpTypeStruct %6
405 %7 = OpTypePointer Uniform %1
406 %3 = OpVariable %7 Uniform
407 %4 = OpVariable %7 Uniform
408 )";
409
410 EXPECT_EQ(RunPass(spirv), result);
411 EXPECT_EQ(GetErrorMessage(), "");
412 }
413
414 // See comment for DontMergeNestedResourceTypes.
TEST_F(RemoveDuplicatesTest,DontMergeResourceTypesContainingArray)415 TEST_F(RemoveDuplicatesTest, DontMergeResourceTypesContainingArray) {
416 const std::string spirv = R"(OpCapability Shader
417 OpMemoryModel Logical GLSL450
418 OpSource HLSL 600
419 OpName %1 "PositionAdjust"
420 OpMemberName %1 0 "XAdjust"
421 OpName %2 "NormalAdjust"
422 OpMemberName %2 0 "XDir"
423 OpName %3 "Constants"
424 OpMemberDecorate %1 0 Offset 0
425 OpMemberDecorate %2 0 Offset 0
426 OpDecorate %3 DescriptorSet 0
427 OpDecorate %3 Binding 0
428 OpDecorate %4 DescriptorSet 1
429 OpDecorate %4 Binding 0
430 %5 = OpTypeFloat 32
431 %6 = OpTypeVector %5 3
432 %1 = OpTypeStruct %6
433 %2 = OpTypeStruct %6
434 %7 = OpTypeInt 32 0
435 %8 = OpConstant %7 4
436 %9 = OpTypeArray %1 %8
437 %10 = OpTypeArray %2 %8
438 %11 = OpTypePointer Uniform %9
439 %12 = OpTypePointer Uniform %10
440 %3 = OpVariable %11 Uniform
441 %4 = OpVariable %12 Uniform
442 )";
443
444 const std::string result = R"(OpCapability Shader
445 OpMemoryModel Logical GLSL450
446 OpSource HLSL 600
447 OpName %1 "PositionAdjust"
448 OpMemberName %1 0 "XAdjust"
449 OpName %3 "Constants"
450 OpMemberDecorate %1 0 Offset 0
451 OpDecorate %3 DescriptorSet 0
452 OpDecorate %3 Binding 0
453 OpDecorate %4 DescriptorSet 1
454 OpDecorate %4 Binding 0
455 %5 = OpTypeFloat 32
456 %6 = OpTypeVector %5 3
457 %1 = OpTypeStruct %6
458 %7 = OpTypeInt 32 0
459 %8 = OpConstant %7 4
460 %9 = OpTypeArray %1 %8
461 %11 = OpTypePointer Uniform %9
462 %3 = OpVariable %11 Uniform
463 %4 = OpVariable %11 Uniform
464 )";
465
466 EXPECT_EQ(RunPass(spirv), result);
467 EXPECT_EQ(GetErrorMessage(), "");
468 }
469
470 // Test that we merge the type of a resource with a type that is not the type
471 // a resource. The resource type appears first in this case. We must keep
472 // the resource type.
TEST_F(RemoveDuplicatesTest,MergeResourceTypeWithNonresourceType1)473 TEST_F(RemoveDuplicatesTest, MergeResourceTypeWithNonresourceType1) {
474 const std::string spirv = R"(OpCapability Shader
475 OpMemoryModel Logical GLSL450
476 OpSource HLSL 600
477 OpName %1 "PositionAdjust"
478 OpMemberName %1 0 "XAdjust"
479 OpName %2 "NormalAdjust"
480 OpMemberName %2 0 "XDir"
481 OpName %3 "Constants"
482 OpMemberDecorate %1 0 Offset 0
483 OpMemberDecorate %2 0 Offset 0
484 OpDecorate %3 DescriptorSet 0
485 OpDecorate %3 Binding 0
486 %4 = OpTypeFloat 32
487 %5 = OpTypeVector %4 3
488 %1 = OpTypeStruct %5
489 %2 = OpTypeStruct %5
490 %6 = OpTypePointer Uniform %1
491 %7 = OpTypePointer Uniform %2
492 %3 = OpVariable %6 Uniform
493 %8 = OpVariable %7 Uniform
494 )";
495
496 const std::string result = R"(OpCapability Shader
497 OpMemoryModel Logical GLSL450
498 OpSource HLSL 600
499 OpName %1 "PositionAdjust"
500 OpMemberName %1 0 "XAdjust"
501 OpName %3 "Constants"
502 OpMemberDecorate %1 0 Offset 0
503 OpDecorate %3 DescriptorSet 0
504 OpDecorate %3 Binding 0
505 %4 = OpTypeFloat 32
506 %5 = OpTypeVector %4 3
507 %1 = OpTypeStruct %5
508 %6 = OpTypePointer Uniform %1
509 %3 = OpVariable %6 Uniform
510 %8 = OpVariable %6 Uniform
511 )";
512
513 EXPECT_EQ(RunPass(spirv), result);
514 EXPECT_EQ(GetErrorMessage(), "");
515 }
516
517 // Test that we merge the type of a resource with a type that is not the type
518 // a resource. The resource type appears second in this case. We must keep
519 // the resource type.
520 //
521 // See comment for DontMergeNestedResourceTypes.
TEST_F(RemoveDuplicatesTest,MergeResourceTypeWithNonresourceType2)522 TEST_F(RemoveDuplicatesTest, MergeResourceTypeWithNonresourceType2) {
523 const std::string spirv = R"(OpCapability Shader
524 OpMemoryModel Logical GLSL450
525 OpSource HLSL 600
526 OpName %1 "PositionAdjust"
527 OpMemberName %1 0 "XAdjust"
528 OpName %2 "NormalAdjust"
529 OpMemberName %2 0 "XDir"
530 OpName %3 "Constants"
531 OpMemberDecorate %1 0 Offset 0
532 OpMemberDecorate %2 0 Offset 0
533 OpDecorate %3 DescriptorSet 0
534 OpDecorate %3 Binding 0
535 %4 = OpTypeFloat 32
536 %5 = OpTypeVector %4 3
537 %1 = OpTypeStruct %5
538 %2 = OpTypeStruct %5
539 %6 = OpTypePointer Uniform %1
540 %7 = OpTypePointer Uniform %2
541 %8 = OpVariable %6 Uniform
542 %3 = OpVariable %7 Uniform
543 )";
544
545 const std::string result = R"(OpCapability Shader
546 OpMemoryModel Logical GLSL450
547 OpSource HLSL 600
548 OpName %1 "PositionAdjust"
549 OpMemberName %1 0 "XAdjust"
550 OpName %3 "Constants"
551 OpMemberDecorate %1 0 Offset 0
552 OpDecorate %3 DescriptorSet 0
553 OpDecorate %3 Binding 0
554 %4 = OpTypeFloat 32
555 %5 = OpTypeVector %4 3
556 %1 = OpTypeStruct %5
557 %6 = OpTypePointer Uniform %1
558 %8 = OpVariable %6 Uniform
559 %3 = OpVariable %6 Uniform
560 )";
561
562 EXPECT_EQ(RunPass(spirv), result);
563 EXPECT_EQ(GetErrorMessage(), "");
564 }
565
566 // In this test, %8 and %9 are the same and only %9 is used in a resource.
567 // However, we cannot merge them unless we also merge %2 and %3, which cannot
568 // happen because both are used in resources.
569 //
570 // If we try to avoid replaces resource types, then remove duplicates should
571 // have not change in this case. That is not currently implemented.
TEST_F(RemoveDuplicatesTest,MergeResourceTypeWithNonresourceType3)572 TEST_F(RemoveDuplicatesTest, MergeResourceTypeWithNonresourceType3) {
573 const std::string spirv = R"(OpCapability Shader
574 OpMemoryModel Logical GLSL450
575 OpEntryPoint GLCompute %1 "main"
576 OpSource HLSL 600
577 OpName %2 "PositionAdjust"
578 OpMemberName %2 0 "XAdjust"
579 OpName %3 "NormalAdjust"
580 OpMemberName %3 0 "XDir"
581 OpName %4 "Constants"
582 OpMemberDecorate %2 0 Offset 0
583 OpMemberDecorate %3 0 Offset 0
584 OpDecorate %4 DescriptorSet 0
585 OpDecorate %4 Binding 0
586 OpDecorate %5 DescriptorSet 1
587 OpDecorate %5 Binding 0
588 %6 = OpTypeFloat 32
589 %7 = OpTypeVector %6 3
590 %2 = OpTypeStruct %7
591 %3 = OpTypeStruct %7
592 %8 = OpTypePointer Uniform %3
593 %9 = OpTypePointer Uniform %2
594 %10 = OpTypeStruct %3
595 %11 = OpTypePointer Uniform %10
596 %5 = OpVariable %9 Uniform
597 %4 = OpVariable %11 Uniform
598 %12 = OpTypeVoid
599 %13 = OpTypeFunction %12
600 %14 = OpTypeInt 32 0
601 %15 = OpConstant %14 0
602 %1 = OpFunction %12 None %13
603 %16 = OpLabel
604 %17 = OpAccessChain %8 %4 %15
605 OpReturn
606 OpFunctionEnd
607 )";
608
609 const std::string result = R"(OpCapability Shader
610 OpMemoryModel Logical GLSL450
611 OpEntryPoint GLCompute %1 "main"
612 OpSource HLSL 600
613 OpName %2 "PositionAdjust"
614 OpMemberName %2 0 "XAdjust"
615 OpName %4 "Constants"
616 OpMemberDecorate %2 0 Offset 0
617 OpDecorate %4 DescriptorSet 0
618 OpDecorate %4 Binding 0
619 OpDecorate %5 DescriptorSet 1
620 OpDecorate %5 Binding 0
621 %6 = OpTypeFloat 32
622 %7 = OpTypeVector %6 3
623 %2 = OpTypeStruct %7
624 %8 = OpTypePointer Uniform %2
625 %10 = OpTypeStruct %2
626 %11 = OpTypePointer Uniform %10
627 %5 = OpVariable %8 Uniform
628 %4 = OpVariable %11 Uniform
629 %12 = OpTypeVoid
630 %13 = OpTypeFunction %12
631 %14 = OpTypeInt 32 0
632 %15 = OpConstant %14 0
633 %1 = OpFunction %12 None %13
634 %16 = OpLabel
635 %17 = OpAccessChain %8 %4 %15
636 OpReturn
637 OpFunctionEnd
638 )";
639
640 EXPECT_EQ(RunPass(spirv), result);
641 EXPECT_EQ(GetErrorMessage(), "");
642 }
643
644 } // namespace
645 } // namespace opt
646 } // namespace spvtools
647