pass_remove_duplicates_test.cpp 17 KB

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