val_data_test.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. // Copyright (c) 2016 Google Inc.
  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. // Validation tests for Data Rules.
  15. #include <sstream>
  16. #include <string>
  17. #include <utility>
  18. #include "gmock/gmock.h"
  19. #include "test/unit_spirv.h"
  20. #include "test/val/val_fixtures.h"
  21. namespace spvtools {
  22. namespace val {
  23. namespace {
  24. using ::testing::HasSubstr;
  25. using ::testing::MatchesRegex;
  26. using ValidateData = spvtest::ValidateBase<std::pair<std::string, bool>>;
  27. std::string HeaderWith(std::string cap) {
  28. return std::string("OpCapability Shader OpCapability Linkage OpCapability ") +
  29. cap + " OpMemoryModel Logical GLSL450 ";
  30. }
  31. std::string header = R"(
  32. OpCapability Shader
  33. OpCapability Linkage
  34. OpMemoryModel Logical GLSL450
  35. )";
  36. std::string header_with_addresses = R"(
  37. OpCapability Addresses
  38. OpCapability Kernel
  39. OpCapability GenericPointer
  40. OpCapability Linkage
  41. OpMemoryModel Physical32 OpenCL
  42. )";
  43. std::string header_with_vec16_cap = R"(
  44. OpCapability Shader
  45. OpCapability Vector16
  46. OpCapability Linkage
  47. OpMemoryModel Logical GLSL450
  48. )";
  49. std::string header_with_int8 = R"(
  50. OpCapability Shader
  51. OpCapability Linkage
  52. OpCapability Int8
  53. OpMemoryModel Logical GLSL450
  54. )";
  55. std::string header_with_int16 = R"(
  56. OpCapability Shader
  57. OpCapability Linkage
  58. OpCapability Int16
  59. OpMemoryModel Logical GLSL450
  60. )";
  61. std::string header_with_int64 = R"(
  62. OpCapability Shader
  63. OpCapability Linkage
  64. OpCapability Int64
  65. OpMemoryModel Logical GLSL450
  66. )";
  67. std::string header_with_float16 = R"(
  68. OpCapability Shader
  69. OpCapability Linkage
  70. OpCapability Float16
  71. OpMemoryModel Logical GLSL450
  72. )";
  73. std::string header_with_float16_buffer = R"(
  74. OpCapability Shader
  75. OpCapability Linkage
  76. OpCapability Float16Buffer
  77. OpMemoryModel Logical GLSL450
  78. )";
  79. std::string header_with_float64 = R"(
  80. OpCapability Shader
  81. OpCapability Linkage
  82. OpCapability Float64
  83. OpMemoryModel Logical GLSL450
  84. )";
  85. std::string invalid_comp_error = "Illegal number of components";
  86. std::string missing_cap_error = "requires the Vector16 capability";
  87. std::string missing_int8_cap_error = "requires the Int8 capability";
  88. std::string missing_int16_cap_error =
  89. "requires the Int16 capability,"
  90. " or an extension that explicitly enables 16-bit integers.";
  91. std::string missing_int64_cap_error = "requires the Int64 capability";
  92. std::string missing_float16_cap_error =
  93. "requires the Float16 or Float16Buffer capability,"
  94. " or an extension that explicitly enables 16-bit floating point.";
  95. std::string missing_float64_cap_error = "requires the Float64 capability";
  96. std::string invalid_num_bits_error = "Invalid number of bits";
  97. TEST_F(ValidateData, vec0) {
  98. std::string str = header + R"(
  99. %1 = OpTypeFloat 32
  100. %2 = OpTypeVector %1 0
  101. )";
  102. CompileSuccessfully(str.c_str());
  103. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  104. EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
  105. }
  106. TEST_F(ValidateData, vec1) {
  107. std::string str = header + R"(
  108. %1 = OpTypeFloat 32
  109. %2 = OpTypeVector %1 1
  110. )";
  111. CompileSuccessfully(str.c_str());
  112. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  113. EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
  114. }
  115. TEST_F(ValidateData, vec2) {
  116. std::string str = header + R"(
  117. %1 = OpTypeFloat 32
  118. %2 = OpTypeVector %1 2
  119. )";
  120. CompileSuccessfully(str.c_str());
  121. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  122. }
  123. TEST_F(ValidateData, vec3) {
  124. std::string str = header + R"(
  125. %1 = OpTypeFloat 32
  126. %2 = OpTypeVector %1 3
  127. )";
  128. CompileSuccessfully(str.c_str());
  129. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  130. }
  131. TEST_F(ValidateData, vec4) {
  132. std::string str = header + R"(
  133. %1 = OpTypeFloat 32
  134. %2 = OpTypeVector %1 4
  135. )";
  136. CompileSuccessfully(str.c_str());
  137. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  138. }
  139. TEST_F(ValidateData, vec5) {
  140. std::string str = header + R"(
  141. %1 = OpTypeFloat 32
  142. %2 = OpTypeVector %1 5
  143. )";
  144. CompileSuccessfully(str.c_str());
  145. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  146. EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
  147. }
  148. TEST_F(ValidateData, vec8) {
  149. std::string str = header + R"(
  150. %1 = OpTypeFloat 32
  151. %2 = OpTypeVector %1 8
  152. )";
  153. CompileSuccessfully(str.c_str());
  154. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  155. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
  156. }
  157. TEST_F(ValidateData, vec8_with_capability) {
  158. std::string str = header_with_vec16_cap + R"(
  159. %1 = OpTypeFloat 32
  160. %2 = OpTypeVector %1 8
  161. )";
  162. CompileSuccessfully(str.c_str());
  163. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  164. }
  165. TEST_F(ValidateData, vec16) {
  166. std::string str = header + R"(
  167. %1 = OpTypeFloat 32
  168. %2 = OpTypeVector %1 8
  169. )";
  170. CompileSuccessfully(str.c_str());
  171. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  172. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_cap_error));
  173. }
  174. TEST_F(ValidateData, vec16_with_capability) {
  175. std::string str = header_with_vec16_cap + R"(
  176. %1 = OpTypeFloat 32
  177. %2 = OpTypeVector %1 16
  178. )";
  179. CompileSuccessfully(str.c_str());
  180. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  181. }
  182. TEST_F(ValidateData, vec15) {
  183. std::string str = header + R"(
  184. %1 = OpTypeFloat 32
  185. %2 = OpTypeVector %1 15
  186. )";
  187. CompileSuccessfully(str.c_str());
  188. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  189. EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_comp_error));
  190. }
  191. TEST_F(ValidateData, int8_good) {
  192. std::string str = header_with_int8 + "%2 = OpTypeInt 8 0";
  193. CompileSuccessfully(str.c_str());
  194. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  195. }
  196. TEST_F(ValidateData, int8_bad) {
  197. std::string str = header + "%2 = OpTypeInt 8 1";
  198. CompileSuccessfully(str.c_str());
  199. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  200. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int8_cap_error));
  201. }
  202. TEST_F(ValidateData, int8_with_storage_buffer_8bit_access_good) {
  203. std::string str = HeaderWith(
  204. "StorageBuffer8BitAccess "
  205. "OpExtension \"SPV_KHR_8bit_storage\"") +
  206. " %2 = OpTypeInt 8 0";
  207. CompileSuccessfully(str.c_str());
  208. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  209. }
  210. TEST_F(ValidateData, int8_with_uniform_and_storage_buffer_8bit_access_good) {
  211. std::string str = HeaderWith(
  212. "UniformAndStorageBuffer8BitAccess "
  213. "OpExtension \"SPV_KHR_8bit_storage\"") +
  214. " %2 = OpTypeInt 8 0";
  215. CompileSuccessfully(str.c_str());
  216. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  217. }
  218. TEST_F(ValidateData, int8_with_storage_push_constant_8_good) {
  219. std::string str = HeaderWith(
  220. "StoragePushConstant8 "
  221. "OpExtension \"SPV_KHR_8bit_storage\"") +
  222. " %2 = OpTypeInt 8 0";
  223. CompileSuccessfully(str.c_str());
  224. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  225. }
  226. TEST_F(ValidateData, int16_good) {
  227. std::string str = header_with_int16 + "%2 = OpTypeInt 16 1";
  228. CompileSuccessfully(str.c_str());
  229. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  230. }
  231. TEST_F(ValidateData, storage_uniform_buffer_block_16_good) {
  232. std::string str = HeaderWith(
  233. "StorageUniformBufferBlock16 "
  234. "OpExtension \"SPV_KHR_16bit_storage\"") +
  235. "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
  236. CompileSuccessfully(str.c_str());
  237. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  238. }
  239. TEST_F(ValidateData, storage_uniform_16_good) {
  240. std::string str =
  241. HeaderWith("StorageUniform16 OpExtension \"SPV_KHR_16bit_storage\"") +
  242. "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
  243. CompileSuccessfully(str.c_str());
  244. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  245. }
  246. TEST_F(ValidateData, storage_push_constant_16_good) {
  247. std::string str = HeaderWith(
  248. "StoragePushConstant16 "
  249. "OpExtension \"SPV_KHR_16bit_storage\"") +
  250. "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
  251. CompileSuccessfully(str.c_str());
  252. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  253. }
  254. TEST_F(ValidateData, storage_input_output_16_good) {
  255. std::string str = HeaderWith(
  256. "StorageInputOutput16 "
  257. "OpExtension \"SPV_KHR_16bit_storage\"") +
  258. "%2 = OpTypeInt 16 1 %3 = OpTypeFloat 16";
  259. CompileSuccessfully(str.c_str());
  260. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  261. }
  262. TEST_F(ValidateData, amd_gpu_shader_half_float_fetch_16_good) {
  263. std::string str = R"(
  264. OpCapability Shader
  265. OpCapability Linkage
  266. OpExtension "SPV_AMD_gpu_shader_half_float_fetch"
  267. OpMemoryModel Logical GLSL450
  268. %2 = OpTypeFloat 16)";
  269. CompileSuccessfully(str.c_str());
  270. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  271. }
  272. TEST_F(ValidateData, int16_bad) {
  273. std::string str = header + "%2 = OpTypeInt 16 1";
  274. CompileSuccessfully(str.c_str());
  275. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  276. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int16_cap_error));
  277. }
  278. TEST_F(ValidateData, int64_good) {
  279. std::string str = header_with_int64 + "%2 = OpTypeInt 64 1";
  280. CompileSuccessfully(str.c_str());
  281. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  282. }
  283. TEST_F(ValidateData, int64_bad) {
  284. std::string str = header + "%2 = OpTypeInt 64 1";
  285. CompileSuccessfully(str.c_str());
  286. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  287. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_int64_cap_error));
  288. }
  289. // Number of bits in an integer may be only one of: {8,16,32,64}
  290. TEST_F(ValidateData, int_invalid_num_bits) {
  291. std::string str = header + "%2 = OpTypeInt 48 1";
  292. CompileSuccessfully(str.c_str());
  293. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  294. EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
  295. }
  296. TEST_F(ValidateData, float16_good) {
  297. std::string str = header_with_float16 + "%2 = OpTypeFloat 16";
  298. CompileSuccessfully(str.c_str());
  299. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  300. }
  301. TEST_F(ValidateData, float16_buffer_good) {
  302. std::string str = header_with_float16_buffer + "%2 = OpTypeFloat 16";
  303. CompileSuccessfully(str.c_str());
  304. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  305. }
  306. TEST_F(ValidateData, float16_bad) {
  307. std::string str = header + "%2 = OpTypeFloat 16";
  308. CompileSuccessfully(str.c_str());
  309. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  310. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float16_cap_error));
  311. }
  312. TEST_F(ValidateData, float64_good) {
  313. std::string str = header_with_float64 + "%2 = OpTypeFloat 64";
  314. CompileSuccessfully(str.c_str());
  315. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  316. }
  317. TEST_F(ValidateData, float64_bad) {
  318. std::string str = header + "%2 = OpTypeFloat 64";
  319. CompileSuccessfully(str.c_str());
  320. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  321. EXPECT_THAT(getDiagnosticString(), HasSubstr(missing_float64_cap_error));
  322. }
  323. // Number of bits in a float may be only one of: {16,32,64}
  324. TEST_F(ValidateData, float_invalid_num_bits) {
  325. std::string str = header + "%2 = OpTypeFloat 48";
  326. CompileSuccessfully(str.c_str());
  327. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  328. EXPECT_THAT(getDiagnosticString(), HasSubstr(invalid_num_bits_error));
  329. }
  330. TEST_F(ValidateData, matrix_data_type_float) {
  331. std::string str = header + R"(
  332. %f32 = OpTypeFloat 32
  333. %vec3 = OpTypeVector %f32 3
  334. %mat33 = OpTypeMatrix %vec3 3
  335. )";
  336. CompileSuccessfully(str.c_str());
  337. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  338. }
  339. TEST_F(ValidateData, ids_should_be_validated_before_data) {
  340. std::string str = header + R"(
  341. %f32 = OpTypeFloat 32
  342. %mat33 = OpTypeMatrix %vec3 3
  343. )";
  344. CompileSuccessfully(str.c_str());
  345. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  346. EXPECT_THAT(getDiagnosticString(),
  347. HasSubstr("Operand 3[%3] requires a previous definition"));
  348. }
  349. TEST_F(ValidateData, matrix_bad_column_type) {
  350. std::string str = header + R"(
  351. %f32 = OpTypeFloat 32
  352. %mat33 = OpTypeMatrix %f32 3
  353. )";
  354. CompileSuccessfully(str.c_str());
  355. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  356. EXPECT_THAT(getDiagnosticString(),
  357. HasSubstr("Columns in a matrix must be of type vector"));
  358. }
  359. TEST_F(ValidateData, matrix_data_type_int) {
  360. std::string str = header + R"(
  361. %int32 = OpTypeInt 32 1
  362. %vec3 = OpTypeVector %int32 3
  363. %mat33 = OpTypeMatrix %vec3 3
  364. )";
  365. CompileSuccessfully(str.c_str());
  366. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  367. EXPECT_THAT(getDiagnosticString(),
  368. HasSubstr("can only be parameterized with floating-point types"));
  369. }
  370. TEST_F(ValidateData, matrix_data_type_bool) {
  371. std::string str = header + R"(
  372. %boolt = OpTypeBool
  373. %vec3 = OpTypeVector %boolt 3
  374. %mat33 = OpTypeMatrix %vec3 3
  375. )";
  376. CompileSuccessfully(str.c_str());
  377. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  378. EXPECT_THAT(getDiagnosticString(),
  379. HasSubstr("can only be parameterized with floating-point types"));
  380. }
  381. TEST_F(ValidateData, matrix_with_0_columns) {
  382. std::string str = header + R"(
  383. %f32 = OpTypeFloat 32
  384. %vec3 = OpTypeVector %f32 3
  385. %mat33 = OpTypeMatrix %vec3 0
  386. )";
  387. CompileSuccessfully(str.c_str());
  388. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  389. EXPECT_THAT(
  390. getDiagnosticString(),
  391. HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
  392. }
  393. TEST_F(ValidateData, matrix_with_1_column) {
  394. std::string str = header + R"(
  395. %f32 = OpTypeFloat 32
  396. %vec3 = OpTypeVector %f32 3
  397. %mat33 = OpTypeMatrix %vec3 1
  398. )";
  399. CompileSuccessfully(str.c_str());
  400. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  401. EXPECT_THAT(
  402. getDiagnosticString(),
  403. HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
  404. }
  405. TEST_F(ValidateData, matrix_with_2_columns) {
  406. std::string str = header + R"(
  407. %f32 = OpTypeFloat 32
  408. %vec3 = OpTypeVector %f32 3
  409. %mat33 = OpTypeMatrix %vec3 2
  410. )";
  411. CompileSuccessfully(str.c_str());
  412. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  413. }
  414. TEST_F(ValidateData, matrix_with_3_columns) {
  415. std::string str = header + R"(
  416. %f32 = OpTypeFloat 32
  417. %vec3 = OpTypeVector %f32 3
  418. %mat33 = OpTypeMatrix %vec3 3
  419. )";
  420. CompileSuccessfully(str.c_str());
  421. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  422. }
  423. TEST_F(ValidateData, matrix_with_4_columns) {
  424. std::string str = header + R"(
  425. %f32 = OpTypeFloat 32
  426. %vec3 = OpTypeVector %f32 3
  427. %mat33 = OpTypeMatrix %vec3 4
  428. )";
  429. CompileSuccessfully(str.c_str());
  430. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  431. }
  432. TEST_F(ValidateData, matrix_with_5_column) {
  433. std::string str = header + R"(
  434. %f32 = OpTypeFloat 32
  435. %vec3 = OpTypeVector %f32 3
  436. %mat33 = OpTypeMatrix %vec3 5
  437. )";
  438. CompileSuccessfully(str.c_str());
  439. ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  440. EXPECT_THAT(
  441. getDiagnosticString(),
  442. HasSubstr("can only be parameterized as having only 2, 3, or 4 columns"));
  443. }
  444. TEST_F(ValidateData, specialize_int) {
  445. std::string str = header + R"(
  446. %i32 = OpTypeInt 32 1
  447. %len = OpSpecConstant %i32 2)";
  448. CompileSuccessfully(str.c_str());
  449. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  450. }
  451. TEST_F(ValidateData, specialize_float) {
  452. std::string str = header + R"(
  453. %f32 = OpTypeFloat 32
  454. %len = OpSpecConstant %f32 2)";
  455. CompileSuccessfully(str.c_str());
  456. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  457. }
  458. TEST_F(ValidateData, specialize_boolean) {
  459. std::string str = header + R"(
  460. %2 = OpTypeBool
  461. %3 = OpSpecConstantTrue %2
  462. %4 = OpSpecConstantFalse %2)";
  463. CompileSuccessfully(str.c_str());
  464. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  465. }
  466. TEST_F(ValidateData, specialize_boolean_true_to_int) {
  467. std::string str = header + R"(
  468. %2 = OpTypeInt 32 1
  469. %3 = OpSpecConstantTrue %2)";
  470. CompileSuccessfully(str.c_str());
  471. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  472. EXPECT_THAT(getDiagnosticString(),
  473. HasSubstr("OpSpecConstantTrue Result Type <id> '1[%int]' is not "
  474. "a boolean type"));
  475. }
  476. TEST_F(ValidateData, specialize_boolean_false_to_int) {
  477. std::string str = header + R"(
  478. %2 = OpTypeInt 32 1
  479. %4 = OpSpecConstantFalse %2)";
  480. CompileSuccessfully(str.c_str());
  481. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  482. EXPECT_THAT(getDiagnosticString(),
  483. HasSubstr("OpSpecConstantFalse Result Type <id> '1[%int]' is not "
  484. "a boolean type"));
  485. }
  486. TEST_F(ValidateData, missing_forward_pointer_decl) {
  487. std::string str = header_with_addresses + R"(
  488. %uintt = OpTypeInt 32 0
  489. %3 = OpTypeStruct %fwd_ptrt %uintt
  490. )";
  491. CompileSuccessfully(str.c_str());
  492. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  493. EXPECT_THAT(getDiagnosticString(),
  494. HasSubstr("Operand 3[%3] requires a previous definition"));
  495. }
  496. TEST_F(ValidateData, missing_forward_pointer_decl_self_reference) {
  497. std::string str = header_with_addresses + R"(
  498. %uintt = OpTypeInt 32 0
  499. %3 = OpTypeStruct %3 %uintt
  500. )";
  501. CompileSuccessfully(str.c_str());
  502. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  503. EXPECT_THAT(
  504. getDiagnosticString(),
  505. HasSubstr("Operand 2[%_struct_2] requires a previous definition"));
  506. }
  507. TEST_F(ValidateData, forward_pointer_missing_definition) {
  508. std::string str = header_with_addresses + R"(
  509. OpTypeForwardPointer %_ptr_Generic_struct_A Generic
  510. %uintt = OpTypeInt 32 0
  511. %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
  512. )";
  513. CompileSuccessfully(str.c_str());
  514. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  515. EXPECT_THAT(getDiagnosticString(),
  516. HasSubstr("forward referenced IDs have not been defined"));
  517. }
  518. TEST_F(ValidateData, forward_ref_bad_type) {
  519. std::string str = header_with_addresses + R"(
  520. OpTypeForwardPointer %_ptr_Generic_struct_A Generic
  521. %uintt = OpTypeInt 32 0
  522. %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
  523. %_ptr_Generic_struct_A = OpTypeFloat 32
  524. )";
  525. CompileSuccessfully(str.c_str());
  526. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  527. EXPECT_THAT(getDiagnosticString(),
  528. HasSubstr("Pointer type in OpTypeForwardPointer is not a pointer "
  529. "type.\n OpTypeForwardPointer %float Generic\n"));
  530. }
  531. TEST_F(ValidateData, forward_ref_points_to_non_struct) {
  532. std::string str = header_with_addresses + R"(
  533. OpTypeForwardPointer %_ptr_Generic_struct_A Generic
  534. %uintt = OpTypeInt 32 0
  535. %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
  536. %_ptr_Generic_struct_A = OpTypePointer Generic %uintt
  537. )";
  538. CompileSuccessfully(str.c_str());
  539. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  540. EXPECT_THAT(getDiagnosticString(),
  541. HasSubstr("Forward pointers must point to a structure"));
  542. }
  543. TEST_F(ValidateData, struct_forward_pointer_good) {
  544. std::string str = header_with_addresses + R"(
  545. OpTypeForwardPointer %_ptr_Generic_struct_A Generic
  546. %uintt = OpTypeInt 32 0
  547. %struct_B = OpTypeStruct %uintt %_ptr_Generic_struct_A
  548. %struct_C = OpTypeStruct %uintt %struct_B
  549. %struct_A = OpTypeStruct %uintt %struct_C
  550. %_ptr_Generic_struct_A = OpTypePointer Generic %struct_C
  551. )";
  552. CompileSuccessfully(str.c_str());
  553. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  554. }
  555. TEST_F(ValidateData, ext_16bit_storage_caps_allow_free_fp_rounding_mode) {
  556. for (const char* cap : {"StorageUniform16", "StorageUniformBufferBlock16"}) {
  557. for (const char* mode : {"RTE", "RTZ", "RTP", "RTN"}) {
  558. std::string str = std::string(R"(
  559. OpCapability Shader
  560. OpCapability Linkage
  561. OpCapability )") +
  562. cap + R"(
  563. OpExtension "SPV_KHR_storage_buffer_storage_class"
  564. OpExtension "SPV_KHR_variable_pointers"
  565. OpExtension "SPV_KHR_16bit_storage"
  566. OpMemoryModel Logical GLSL450
  567. OpDecorate %_ FPRoundingMode )" + mode + R"(
  568. %half = OpTypeFloat 16
  569. %float = OpTypeFloat 32
  570. %float_1_25 = OpConstant %float 1.25
  571. %half_ptr = OpTypePointer StorageBuffer %half
  572. %half_ptr_var = OpVariable %half_ptr StorageBuffer
  573. %void = OpTypeVoid
  574. %func = OpTypeFunction %void
  575. %main = OpFunction %void None %func
  576. %main_entry = OpLabel
  577. %_ = OpFConvert %half %float_1_25
  578. OpStore %half_ptr_var %_
  579. OpReturn
  580. OpFunctionEnd
  581. )";
  582. CompileSuccessfully(str.c_str());
  583. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  584. }
  585. }
  586. }
  587. TEST_F(ValidateData, vulkan_disallow_free_fp_rounding_mode) {
  588. for (const char* mode : {"RTE", "RTZ"}) {
  589. for (const auto env : {SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1}) {
  590. std::string str = std::string(R"(
  591. OpCapability Shader
  592. OpExtension "SPV_KHR_storage_buffer_storage_class"
  593. OpExtension "SPV_KHR_variable_pointers"
  594. OpMemoryModel Logical GLSL450
  595. OpDecorate %_ FPRoundingMode )") +
  596. mode + R"(
  597. %half = OpTypeFloat 16
  598. %float = OpTypeFloat 32
  599. %float_1_25 = OpConstant %float 1.25
  600. %half_ptr = OpTypePointer StorageBuffer %half
  601. %half_ptr_var = OpVariable %half_ptr StorageBuffer
  602. %void = OpTypeVoid
  603. %func = OpTypeFunction %void
  604. %main = OpFunction %void None %func
  605. %main_entry = OpLabel
  606. %_ = OpFConvert %half %float_1_25
  607. OpStore %half_ptr_var %_
  608. OpReturn
  609. OpFunctionEnd
  610. )";
  611. CompileSuccessfully(str.c_str());
  612. ASSERT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions(env));
  613. EXPECT_THAT(
  614. getDiagnosticString(),
  615. HasSubstr(
  616. "Operand 2 of Decorate requires one of these capabilities: "
  617. "StorageBuffer16BitAccess UniformAndStorageBuffer16BitAccess "
  618. "StoragePushConstant16 StorageInputOutput16"));
  619. }
  620. }
  621. }
  622. TEST_F(ValidateData, void_array) {
  623. std::string str = header + R"(
  624. %void = OpTypeVoid
  625. %int = OpTypeInt 32 0
  626. %int_5 = OpConstant %int 5
  627. %array = OpTypeArray %void %int_5
  628. )";
  629. CompileSuccessfully(str.c_str());
  630. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  631. EXPECT_THAT(
  632. getDiagnosticString(),
  633. HasSubstr("OpTypeArray Element Type <id> '1[%void]' is a void type."));
  634. }
  635. TEST_F(ValidateData, void_runtime_array) {
  636. std::string str = header + R"(
  637. %void = OpTypeVoid
  638. %array = OpTypeRuntimeArray %void
  639. )";
  640. CompileSuccessfully(str.c_str());
  641. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  642. EXPECT_THAT(
  643. getDiagnosticString(),
  644. HasSubstr(
  645. "OpTypeRuntimeArray Element Type <id> '1[%void]' is a void type."));
  646. }
  647. TEST_F(ValidateData, vulkan_RTA_array_at_end_of_struct) {
  648. std::string str = R"(
  649. OpCapability Shader
  650. OpMemoryModel Logical GLSL450
  651. OpEntryPoint Fragment %func "func"
  652. OpExecutionMode %func OriginUpperLeft
  653. OpDecorate %array_t ArrayStride 4
  654. OpMemberDecorate %struct_t 0 Offset 0
  655. OpMemberDecorate %struct_t 1 Offset 4
  656. OpDecorate %struct_t Block
  657. %uint_t = OpTypeInt 32 0
  658. %array_t = OpTypeRuntimeArray %uint_t
  659. %struct_t = OpTypeStruct %uint_t %array_t
  660. %struct_ptr = OpTypePointer StorageBuffer %struct_t
  661. %2 = OpVariable %struct_ptr StorageBuffer
  662. %void = OpTypeVoid
  663. %func_t = OpTypeFunction %void
  664. %func = OpFunction %void None %func_t
  665. %1 = OpLabel
  666. OpReturn
  667. OpFunctionEnd
  668. )";
  669. CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
  670. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  671. }
  672. TEST_F(ValidateData, vulkan_RTA_not_at_end_of_struct) {
  673. std::string str = R"(
  674. OpCapability Shader
  675. OpMemoryModel Logical GLSL450
  676. OpEntryPoint Fragment %func "func"
  677. OpExecutionMode %func OriginUpperLeft
  678. OpDecorate %array_t ArrayStride 4
  679. OpMemberDecorate %struct_t 0 Offset 0
  680. OpMemberDecorate %struct_t 1 Offset 4
  681. OpDecorate %struct_t Block
  682. %uint_t = OpTypeInt 32 0
  683. %array_t = OpTypeRuntimeArray %uint_t
  684. %struct_t = OpTypeStruct %array_t %uint_t
  685. %struct_ptr = OpTypePointer StorageBuffer %struct_t
  686. %2 = OpVariable %struct_ptr StorageBuffer
  687. %void = OpTypeVoid
  688. %func_t = OpTypeFunction %void
  689. %func = OpFunction %void None %func_t
  690. %1 = OpLabel
  691. OpReturn
  692. OpFunctionEnd
  693. )";
  694. CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
  695. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
  696. EXPECT_THAT(getDiagnosticString(),
  697. HasSubstr("In Vulkan, OpTypeRuntimeArray must only be used for "
  698. "the last member of an OpTypeStruct\n %_struct_3 = "
  699. "OpTypeStruct %_runtimearr_uint %uint\n"));
  700. }
  701. TEST_F(ValidateData, TypeForwardReference) {
  702. std::string test = R"(
  703. OpCapability Shader
  704. OpCapability PhysicalStorageBufferAddresses
  705. OpCapability Linkage
  706. OpMemoryModel Logical GLSL450
  707. OpTypeForwardPointer %1 PhysicalStorageBuffer
  708. %2 = OpTypeStruct
  709. %3 = OpTypeRuntimeArray %1
  710. %1 = OpTypePointer PhysicalStorageBuffer %2
  711. )";
  712. CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
  713. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
  714. }
  715. TEST_F(ValidateData, VulkanTypeForwardStorageClass) {
  716. std::string test = R"(
  717. OpCapability Shader
  718. OpCapability PhysicalStorageBufferAddresses
  719. OpMemoryModel Logical GLSL450
  720. OpTypeForwardPointer %1 Uniform
  721. %2 = OpTypeStruct
  722. %3 = OpTypeRuntimeArray %1
  723. %1 = OpTypePointer Uniform %2
  724. )";
  725. CompileSuccessfully(test, SPV_ENV_VULKAN_1_2);
  726. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
  727. EXPECT_THAT(getDiagnosticString(),
  728. AnyVUID("VUID-StandaloneSpirv-OpTypeForwardPointer-04711"));
  729. EXPECT_THAT(getDiagnosticString(),
  730. HasSubstr("In Vulkan, OpTypeForwardPointer must have "
  731. "a storage class of PhysicalStorageBuffer."));
  732. }
  733. TEST_F(ValidateData, TypeForwardReferenceMustBeForwardPointer) {
  734. std::string test = R"(
  735. OpCapability Shader
  736. OpCapability PhysicalStorageBufferAddresses
  737. OpCapability Linkage
  738. OpMemoryModel Logical GLSL450
  739. %1 = OpTypeStruct
  740. %2 = OpTypeRuntimeArray %3
  741. %3 = OpTypePointer PhysicalStorageBuffer %1
  742. )";
  743. CompileSuccessfully(test, SPV_ENV_UNIVERSAL_1_5);
  744. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
  745. EXPECT_THAT(getDiagnosticString(),
  746. HasSubstr("Operand 3[%_ptr_PhysicalStorageBuffer__struct_1] "
  747. "requires a previous definition"));
  748. }
  749. } // namespace
  750. } // namespace val
  751. } // namespace spvtools