c_interface_test.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. // Copyright (c) 2023 Nintendo
  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 <string>
  15. #include <iostream>
  16. #include "gtest/gtest.h"
  17. #include "spirv-tools/libspirv.h"
  18. namespace spvtools {
  19. namespace {
  20. TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForInvalidInput) {
  21. const uint32_t spirv[] = {
  22. 0xDEADFEED, // Invalid Magic
  23. 0x00010100, // Version 1.1
  24. 0x00000000, // No Generator
  25. 0x01000000, // Bound
  26. 0x00000000, // Schema
  27. 0x00020011, // OpCapability
  28. 0x00000001, // Shader
  29. 0x00020011, // OpCapability
  30. 0x00000005, // Linkage
  31. 0x0003000E, // OpMemoryModel
  32. 0x00000000, // Logical
  33. 0x00000001 // GLSL450
  34. };
  35. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  36. ASSERT_NE(optimizer, nullptr);
  37. // Do not register any passes
  38. auto options = spvOptimizerOptionsCreate();
  39. ASSERT_NE(options, nullptr);
  40. spvOptimizerOptionsSetRunValidator(options, true);
  41. spv_binary binary = nullptr;
  42. EXPECT_NE(SPV_SUCCESS,
  43. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  44. &binary, options));
  45. ASSERT_EQ(binary, nullptr);
  46. spvOptimizerOptionsDestroy(options);
  47. spvOptimizerDestroy(optimizer);
  48. }
  49. TEST(OptimizerCInterface, SpecifyConsumerWithValidationNoPassesForInvalidInput) {
  50. const uint32_t spirv[] = {
  51. 0xDEADFEED, // Invalid Magic
  52. 0x00010100, // Version 1.1
  53. 0x00000000, // No Generator
  54. 0x01000000, // Bound
  55. 0x00000000, // Schema
  56. 0x00020011, // OpCapability
  57. 0x00000001, // Shader
  58. 0x00020011, // OpCapability
  59. 0x00000005, // Linkage
  60. 0x0003000E, // OpMemoryModel
  61. 0x00000000, // Logical
  62. 0x00000001 // GLSL450
  63. };
  64. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  65. ASSERT_NE(optimizer, nullptr);
  66. spvOptimizerSetMessageConsumer(
  67. optimizer,
  68. [](spv_message_level_t, const char*, const spv_position_t*,
  69. const char* message) {
  70. std::cout << message << std::endl;
  71. });
  72. // Do not register any passes
  73. auto options = spvOptimizerOptionsCreate();
  74. ASSERT_NE(options, nullptr);
  75. spvOptimizerOptionsSetRunValidator(options, true);
  76. testing::internal::CaptureStdout();
  77. spv_binary binary = nullptr;
  78. EXPECT_NE(SPV_SUCCESS,
  79. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  80. &binary, options));
  81. ASSERT_EQ(binary, nullptr);
  82. auto output = testing::internal::GetCapturedStdout();
  83. EXPECT_STRNE(output.c_str(), "");
  84. spvOptimizerOptionsDestroy(options);
  85. spvOptimizerDestroy(optimizer);
  86. }
  87. TEST(OptimizerCInterface, DefaultConsumerWithValidationNoPassesForValidInput) {
  88. const uint32_t spirv[] = {
  89. 0x07230203, // Magic
  90. 0x00010100, // Version 1.1
  91. 0x00000000, // No Generator
  92. 0x00000001, // Bound
  93. 0x00000000, // Schema
  94. 0x00020011, // OpCapability
  95. 0x00000001, // Shader
  96. 0x00020011, // OpCapability
  97. 0x00000005, // Linkage
  98. 0x0003000E, // OpMemoryModel
  99. 0x00000000, // Logical
  100. 0x00000001 // GLSL450
  101. };
  102. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  103. ASSERT_NE(optimizer, nullptr);
  104. // Do not register any passes
  105. auto options = spvOptimizerOptionsCreate();
  106. ASSERT_NE(options, nullptr);
  107. spvOptimizerOptionsSetRunValidator(options, true);
  108. spv_binary binary = nullptr;
  109. EXPECT_EQ(SPV_SUCCESS,
  110. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  111. &binary, options));
  112. ASSERT_NE(binary, nullptr);
  113. spvOptimizerOptionsDestroy(options);
  114. // Should remain unchanged
  115. EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t));
  116. EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0);
  117. spvBinaryDestroy(binary);
  118. spvOptimizerDestroy(optimizer);
  119. }
  120. TEST(OptimizerCInterface, DefaultConsumerNoPassesForValidInput) {
  121. const uint32_t spirv[] = {
  122. 0x07230203, // Magic
  123. 0x00010100, // Version 1.1
  124. 0x00000000, // No Generator
  125. 0x00000003, // Bound
  126. 0x00000000, // Schema
  127. 0x00020011, // OpCapability
  128. 0x00000001, // Shader
  129. 0x00020011, // OpCapability
  130. 0x00000005, // Linkage
  131. 0x0003000E, // OpMemoryModel
  132. 0x00000000, // Logical
  133. 0x00000001, // GLSL450
  134. 0x00040015, // OpTypeInt
  135. 0x00000001, // %1
  136. 0x00000020, // 32 Bits
  137. 0x00000000, // Unsigned
  138. 0x0004002B, // OpConstant
  139. 0x00000001, // %1
  140. 0x00000002, // %2
  141. 0x00000001 // 1
  142. };
  143. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  144. ASSERT_NE(optimizer, nullptr);
  145. // Do not register any passes
  146. auto options = spvOptimizerOptionsCreate();
  147. ASSERT_NE(options, nullptr);
  148. spvOptimizerOptionsSetRunValidator(options, true);
  149. spv_binary binary = nullptr;
  150. EXPECT_EQ(SPV_SUCCESS,
  151. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  152. &binary, options));
  153. ASSERT_NE(binary, nullptr);
  154. spvOptimizerOptionsDestroy(options);
  155. // Should remain unchanged
  156. EXPECT_EQ(binary->wordCount, sizeof(spirv) / sizeof(uint32_t));
  157. EXPECT_EQ(memcmp(binary->code, spirv, sizeof(spirv) / sizeof(uint32_t)), 0);
  158. spvBinaryDestroy(binary);
  159. spvOptimizerDestroy(optimizer);
  160. }
  161. TEST(OptimizerCInterface, DefaultConsumerLegalizationPassesForValidInput) {
  162. const uint32_t spirv[] = {
  163. 0x07230203, // Magic
  164. 0x00010100, // Version 1.1
  165. 0x00000000, // No Generator
  166. 0x00000003, // Bound
  167. 0x00000000, // Schema
  168. 0x00020011, // OpCapability
  169. 0x00000001, // Shader
  170. 0x00020011, // OpCapability
  171. 0x00000005, // Linkage
  172. 0x0003000E, // OpMemoryModel
  173. 0x00000000, // Logical
  174. 0x00000001, // GLSL450
  175. 0x00040015, // OpTypeInt
  176. 0x00000001, // %1
  177. 0x00000020, // 32 Bits
  178. 0x00000000, // Unsigned
  179. 0x0004002B, // OpConstant
  180. 0x00000001, // %1
  181. 0x00000002, // %2
  182. 0x00000001 // 1
  183. };
  184. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  185. ASSERT_NE(optimizer, nullptr);
  186. spvOptimizerRegisterLegalizationPasses(optimizer);
  187. auto options = spvOptimizerOptionsCreate();
  188. ASSERT_NE(options, nullptr);
  189. spvOptimizerOptionsSetRunValidator(options, false);
  190. spv_binary binary = nullptr;
  191. EXPECT_EQ(SPV_SUCCESS,
  192. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  193. &binary, options));
  194. ASSERT_NE(binary, nullptr);
  195. spvOptimizerOptionsDestroy(options);
  196. // Only check that SPV_SUCCESS is returned, do not verify output
  197. spvBinaryDestroy(binary);
  198. spvOptimizerDestroy(optimizer);
  199. }
  200. TEST(OptimizerCInterface, DefaultConsumerPerformancePassesForValidInput) {
  201. const uint32_t spirv[] = {
  202. 0x07230203, // Magic
  203. 0x00010100, // Version 1.1
  204. 0x00000000, // No Generator
  205. 0x00000003, // Bound
  206. 0x00000000, // Schema
  207. 0x00020011, // OpCapability
  208. 0x00000001, // Shader
  209. 0x00020011, // OpCapability
  210. 0x00000005, // Linkage
  211. 0x0003000E, // OpMemoryModel
  212. 0x00000000, // Logical
  213. 0x00000001, // GLSL450
  214. 0x00040015, // OpTypeInt
  215. 0x00000001, // %1
  216. 0x00000020, // 32 Bits
  217. 0x00000000, // Unsigned
  218. 0x0004002B, // OpConstant
  219. 0x00000001, // %1
  220. 0x00000002, // %2
  221. 0x00000001 // 1
  222. };
  223. const uint32_t expected_spirv[] = {
  224. 0x07230203, // Magic
  225. 0x00010100, // Version 1.1
  226. 0x00000000, // No Generator
  227. 0x00000001, // Bound
  228. 0x00000000, // Schema
  229. 0x00020011, // OpCapability
  230. 0x00000001, // Shader
  231. 0x00020011, // OpCapability
  232. 0x00000005, // Linkage
  233. 0x0003000E, // OpMemoryModel
  234. 0x00000000, // Logical
  235. 0x00000001 // GLSL450
  236. };
  237. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  238. ASSERT_NE(optimizer, nullptr);
  239. spvOptimizerRegisterPerformancePasses(optimizer);
  240. auto options = spvOptimizerOptionsCreate();
  241. ASSERT_NE(options, nullptr);
  242. spvOptimizerOptionsSetRunValidator(options, false);
  243. spv_binary binary = nullptr;
  244. EXPECT_EQ(SPV_SUCCESS,
  245. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  246. &binary, options));
  247. ASSERT_NE(binary, nullptr);
  248. spvOptimizerOptionsDestroy(options);
  249. // Unreferenced OpTypeInt and OpConstant should be removed
  250. EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
  251. EXPECT_EQ(memcmp(binary->code, expected_spirv,
  252. sizeof(expected_spirv) / sizeof(uint32_t)), 0);
  253. spvBinaryDestroy(binary);
  254. spvOptimizerDestroy(optimizer);
  255. }
  256. TEST(OptimizerCInterface, DefaultConsumerSizePassesForValidInput) {
  257. const uint32_t spirv[] = {
  258. 0x07230203, // Magic
  259. 0x00010100, // Version 1.1
  260. 0x00000000, // No Generator
  261. 0x00000003, // Bound
  262. 0x00000000, // Schema
  263. 0x00020011, // OpCapability
  264. 0x00000001, // Shader
  265. 0x00020011, // OpCapability
  266. 0x00000005, // Linkage
  267. 0x0003000E, // OpMemoryModel
  268. 0x00000000, // Logical
  269. 0x00000001, // GLSL450
  270. 0x00040015, // OpTypeInt
  271. 0x00000001, // %1
  272. 0x00000020, // 32 Bits
  273. 0x00000000, // Unsigned
  274. 0x0004002B, // OpConstant
  275. 0x00000001, // %1
  276. 0x00000002, // %2
  277. 0x00000001 // 1
  278. };
  279. const uint32_t expected_spirv[] = {
  280. 0x07230203, // Magic
  281. 0x00010100, // Version 1.1
  282. 0x00000000, // No Generator
  283. 0x00000001, // Bound
  284. 0x00000000, // Schema
  285. 0x00020011, // OpCapability
  286. 0x00000001, // Shader
  287. 0x00020011, // OpCapability
  288. 0x00000005, // Linkage
  289. 0x0003000E, // OpMemoryModel
  290. 0x00000000, // Logical
  291. 0x00000001 // GLSL450
  292. };
  293. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  294. ASSERT_NE(optimizer, nullptr);
  295. spvOptimizerRegisterSizePasses(optimizer);
  296. auto options = spvOptimizerOptionsCreate();
  297. ASSERT_NE(options, nullptr);
  298. spvOptimizerOptionsSetRunValidator(options, false);
  299. spv_binary binary = nullptr;
  300. EXPECT_EQ(SPV_SUCCESS,
  301. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  302. &binary, options));
  303. ASSERT_NE(binary, nullptr);
  304. spvOptimizerOptionsDestroy(options);
  305. // Unreferenced OpTypeInt and OpConstant should be removed
  306. EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
  307. EXPECT_EQ(memcmp(binary->code, expected_spirv,
  308. sizeof(expected_spirv) / sizeof(uint32_t)), 0);
  309. spvBinaryDestroy(binary);
  310. spvOptimizerDestroy(optimizer);
  311. }
  312. TEST(OptimizerCInterface, DefaultConsumerPassFromFlagForValidInput) {
  313. const uint32_t spirv[] = {
  314. 0x07230203, // Magic
  315. 0x00010100, // Version 1.1
  316. 0x00000000, // No Generator
  317. 0x00000003, // Bound
  318. 0x00000000, // Schema
  319. 0x00020011, // OpCapability
  320. 0x00000001, // Shader
  321. 0x00020011, // OpCapability
  322. 0x00000005, // Linkage
  323. 0x0003000E, // OpMemoryModel
  324. 0x00000000, // Logical
  325. 0x00000001, // GLSL450
  326. 0x00040015, // OpTypeInt
  327. 0x00000001, // %1
  328. 0x00000020, // 32 Bits
  329. 0x00000000, // Unsigned
  330. 0x0004002B, // OpConstant
  331. 0x00000001, // %1
  332. 0x00000002, // %2
  333. 0x00000001 // 1
  334. };
  335. const uint32_t expected_spirv[] = {
  336. 0x07230203, // Magic
  337. 0x00010100, // Version 1.1
  338. 0x00000000, // No Generator
  339. 0x00000001, // Bound
  340. 0x00000000, // Schema
  341. 0x00020011, // OpCapability
  342. 0x00000001, // Shader
  343. 0x00020011, // OpCapability
  344. 0x00000005, // Linkage
  345. 0x0003000E, // OpMemoryModel
  346. 0x00000000, // Logical
  347. 0x00000001 // GLSL450
  348. };
  349. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  350. ASSERT_NE(optimizer, nullptr);
  351. EXPECT_TRUE(spvOptimizerRegisterPassFromFlag(
  352. optimizer, "--eliminate-dead-code-aggressive"));
  353. auto options = spvOptimizerOptionsCreate();
  354. ASSERT_NE(options, nullptr);
  355. spvOptimizerOptionsSetRunValidator(options, false);
  356. spv_binary binary = nullptr;
  357. EXPECT_EQ(SPV_SUCCESS,
  358. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  359. &binary, options));
  360. ASSERT_NE(binary, nullptr);
  361. spvOptimizerOptionsDestroy(options);
  362. // Unreferenced OpTypeInt and OpConstant should be removed
  363. EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
  364. EXPECT_EQ(memcmp(binary->code, expected_spirv,
  365. sizeof(expected_spirv) / sizeof(uint32_t)), 0);
  366. spvBinaryDestroy(binary);
  367. spvOptimizerDestroy(optimizer);
  368. }
  369. TEST(OptimizerCInterface, DefaultConsumerPassesFromFlagsForValidInput) {
  370. const uint32_t spirv[] = {
  371. 0x07230203, // Magic
  372. 0x00010100, // Version 1.1
  373. 0x00000000, // No Generator
  374. 0x00000003, // Bound
  375. 0x00000000, // Schema
  376. 0x00020011, // OpCapability
  377. 0x00000001, // Shader
  378. 0x00020011, // OpCapability
  379. 0x00000005, // Linkage
  380. 0x0003000E, // OpMemoryModel
  381. 0x00000000, // Logical
  382. 0x00000001, // GLSL450
  383. 0x00040015, // OpTypeInt
  384. 0x00000001, // %1
  385. 0x00000020, // 32 Bits
  386. 0x00000000, // Unsigned
  387. 0x0004002B, // OpConstant
  388. 0x00000001, // %1
  389. 0x00000002, // %2
  390. 0x00000001 // 1
  391. };
  392. const uint32_t expected_spirv[] = {
  393. 0x07230203, // Magic
  394. 0x00010100, // Version 1.1
  395. 0x00000000, // No Generator
  396. 0x00000001, // Bound
  397. 0x00000000, // Schema
  398. 0x00020011, // OpCapability
  399. 0x00000001, // Shader
  400. 0x00020011, // OpCapability
  401. 0x00000005, // Linkage
  402. 0x0003000E, // OpMemoryModel
  403. 0x00000000, // Logical
  404. 0x00000001 // GLSL450
  405. };
  406. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  407. ASSERT_NE(optimizer, nullptr);
  408. const char* flags[2] = {
  409. "--eliminate-dead-const",
  410. "--eliminate-dead-code-aggressive"
  411. };
  412. EXPECT_TRUE(spvOptimizerRegisterPassesFromFlags(
  413. optimizer, flags, sizeof(flags) / sizeof(const char*)));
  414. auto options = spvOptimizerOptionsCreate();
  415. ASSERT_NE(options, nullptr);
  416. spvOptimizerOptionsSetRunValidator(options, false);
  417. spv_binary binary = nullptr;
  418. EXPECT_EQ(SPV_SUCCESS,
  419. spvOptimizerRun(optimizer, spirv, sizeof(spirv) / sizeof(uint32_t),
  420. &binary, options));
  421. ASSERT_NE(binary, nullptr);
  422. spvOptimizerOptionsDestroy(options);
  423. // Unreferenced OpTypeInt and OpConstant should be removed
  424. EXPECT_EQ(binary->wordCount, sizeof(expected_spirv) / sizeof(uint32_t));
  425. EXPECT_EQ(memcmp(binary->code, expected_spirv,
  426. sizeof(expected_spirv) / sizeof(uint32_t)), 0);
  427. spvBinaryDestroy(binary);
  428. spvOptimizerDestroy(optimizer);
  429. }
  430. TEST(OptimizerCInterface, DefaultConsumerInvalidPassFromFlag) {
  431. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  432. ASSERT_NE(optimizer, nullptr);
  433. EXPECT_FALSE(spvOptimizerRegisterPassFromFlag(
  434. optimizer, "--this-is-not-a-valid-pass"));
  435. spvOptimizerDestroy(optimizer);
  436. }
  437. TEST(OptimizerCInterface, DefaultConsumerInvalidPassesFromFlags) {
  438. auto optimizer = spvOptimizerCreate(SPV_ENV_UNIVERSAL_1_1);
  439. ASSERT_NE(optimizer, nullptr);
  440. const char* flags[2] = {
  441. "--eliminate-dead-const",
  442. "--this-is-not-a-valid-pass"
  443. };
  444. EXPECT_FALSE(spvOptimizerRegisterPassesFromFlags(
  445. optimizer, flags, sizeof(flags) / sizeof(const char*)));
  446. spvOptimizerDestroy(optimizer);
  447. }
  448. } // namespace
  449. } // namespace spvtools