val_function_test.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. // Copyright (c) 2019 Google LLC.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <sstream>
  15. #include <string>
  16. #include <tuple>
  17. #include "gmock/gmock.h"
  18. #include "test/test_fixture.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::Combine;
  25. using ::testing::HasSubstr;
  26. using ::testing::Values;
  27. using ValidateFunctionCall = spvtest::ValidateBase<std::string>;
  28. std::string GenerateShader(const std::string& storage_class,
  29. const std::string& capabilities,
  30. const std::string& extensions) {
  31. std::string spirv = R"(
  32. OpCapability Shader
  33. OpCapability Linkage
  34. OpCapability AtomicStorage
  35. )" + capabilities + R"(
  36. OpExtension "SPV_KHR_storage_buffer_storage_class"
  37. )" +
  38. extensions + R"(
  39. OpMemoryModel Logical GLSL450
  40. OpName %var "var"
  41. %void = OpTypeVoid
  42. %int = OpTypeInt 32 0
  43. %ptr = OpTypePointer )" + storage_class + R"( %int
  44. %caller_ty = OpTypeFunction %void
  45. %callee_ty = OpTypeFunction %void %ptr
  46. )";
  47. if (storage_class != "Function") {
  48. spirv += "%var = OpVariable %ptr " + storage_class;
  49. }
  50. spirv += R"(
  51. %caller = OpFunction %void None %caller_ty
  52. %1 = OpLabel
  53. )";
  54. if (storage_class == "Function") {
  55. spirv += "%var = OpVariable %ptr Function";
  56. }
  57. spirv += R"(
  58. %call = OpFunctionCall %void %callee %var
  59. OpReturn
  60. OpFunctionEnd
  61. %callee = OpFunction %void None %callee_ty
  62. %param = OpFunctionParameter %ptr
  63. %2 = OpLabel
  64. OpReturn
  65. OpFunctionEnd
  66. )";
  67. return spirv;
  68. }
  69. std::string GenerateShaderParameter(const std::string& storage_class,
  70. const std::string& capabilities,
  71. const std::string& extensions) {
  72. std::string spirv = R"(
  73. OpCapability Shader
  74. OpCapability Linkage
  75. OpCapability AtomicStorage
  76. )" + capabilities + R"(
  77. OpExtension "SPV_KHR_storage_buffer_storage_class"
  78. )" +
  79. extensions + R"(
  80. OpMemoryModel Logical GLSL450
  81. OpName %p "p"
  82. %void = OpTypeVoid
  83. %int = OpTypeInt 32 0
  84. %ptr = OpTypePointer )" + storage_class + R"( %int
  85. %func_ty = OpTypeFunction %void %ptr
  86. %caller = OpFunction %void None %func_ty
  87. %p = OpFunctionParameter %ptr
  88. %1 = OpLabel
  89. %call = OpFunctionCall %void %callee %p
  90. OpReturn
  91. OpFunctionEnd
  92. %callee = OpFunction %void None %func_ty
  93. %param = OpFunctionParameter %ptr
  94. %2 = OpLabel
  95. OpReturn
  96. OpFunctionEnd
  97. )";
  98. return spirv;
  99. }
  100. std::string GenerateShaderAccessChain(const std::string& storage_class,
  101. const std::string& capabilities,
  102. const std::string& extensions) {
  103. std::string spirv = R"(
  104. OpCapability Shader
  105. OpCapability Linkage
  106. OpCapability AtomicStorage
  107. )" + capabilities + R"(
  108. OpExtension "SPV_KHR_storage_buffer_storage_class"
  109. )" +
  110. extensions + R"(
  111. OpMemoryModel Logical GLSL450
  112. OpName %var "var"
  113. OpName %gep "gep"
  114. %void = OpTypeVoid
  115. %int = OpTypeInt 32 0
  116. %int2 = OpTypeVector %int 2
  117. %int_0 = OpConstant %int 0
  118. %ptr = OpTypePointer )" + storage_class + R"( %int2
  119. %ptr2 = OpTypePointer )" +
  120. storage_class + R"( %int
  121. %caller_ty = OpTypeFunction %void
  122. %callee_ty = OpTypeFunction %void %ptr2
  123. )";
  124. if (storage_class != "Function") {
  125. spirv += "%var = OpVariable %ptr " + storage_class;
  126. }
  127. spirv += R"(
  128. %caller = OpFunction %void None %caller_ty
  129. %1 = OpLabel
  130. )";
  131. if (storage_class == "Function") {
  132. spirv += "%var = OpVariable %ptr Function";
  133. }
  134. spirv += R"(
  135. %gep = OpAccessChain %ptr2 %var %int_0
  136. %call = OpFunctionCall %void %callee %gep
  137. OpReturn
  138. OpFunctionEnd
  139. %callee = OpFunction %void None %callee_ty
  140. %param = OpFunctionParameter %ptr2
  141. %2 = OpLabel
  142. OpReturn
  143. OpFunctionEnd
  144. )";
  145. return spirv;
  146. }
  147. TEST_P(ValidateFunctionCall, VariableNoVariablePointers) {
  148. const std::string storage_class = GetParam();
  149. std::string spirv = GenerateShader(storage_class, "", "");
  150. const std::vector<std::string> valid_storage_classes = {
  151. "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"};
  152. bool valid =
  153. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  154. storage_class) != valid_storage_classes.end();
  155. CompileSuccessfully(spirv);
  156. if (valid) {
  157. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  158. } else {
  159. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  160. if (storage_class == "StorageBuffer") {
  161. EXPECT_THAT(
  162. getDiagnosticString(),
  163. HasSubstr("StorageBuffer pointer operand '1[%var]' requires a "
  164. "variable pointers capability"));
  165. } else {
  166. EXPECT_THAT(
  167. getDiagnosticString(),
  168. HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
  169. }
  170. }
  171. }
  172. TEST_P(ValidateFunctionCall, VariableVariablePointersStorageClass) {
  173. const std::string storage_class = GetParam();
  174. std::string spirv = GenerateShader(
  175. storage_class, "OpCapability VariablePointersStorageBuffer",
  176. "OpExtension \"SPV_KHR_variable_pointers\"");
  177. const std::vector<std::string> valid_storage_classes = {
  178. "UniformConstant", "Function", "Private",
  179. "Workgroup", "StorageBuffer", "AtomicCounter"};
  180. bool valid =
  181. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  182. storage_class) != valid_storage_classes.end();
  183. CompileSuccessfully(spirv);
  184. if (valid) {
  185. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  186. } else {
  187. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  188. EXPECT_THAT(
  189. getDiagnosticString(),
  190. HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
  191. }
  192. }
  193. TEST_P(ValidateFunctionCall, VariableVariablePointers) {
  194. const std::string storage_class = GetParam();
  195. std::string spirv =
  196. GenerateShader(storage_class, "OpCapability VariablePointers",
  197. "OpExtension \"SPV_KHR_variable_pointers\"");
  198. const std::vector<std::string> valid_storage_classes = {
  199. "UniformConstant", "Function", "Private",
  200. "Workgroup", "StorageBuffer", "AtomicCounter"};
  201. bool valid =
  202. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  203. storage_class) != valid_storage_classes.end();
  204. CompileSuccessfully(spirv);
  205. if (valid) {
  206. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  207. } else {
  208. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  209. EXPECT_THAT(
  210. getDiagnosticString(),
  211. HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
  212. }
  213. }
  214. TEST_P(ValidateFunctionCall, ParameterNoVariablePointers) {
  215. const std::string storage_class = GetParam();
  216. std::string spirv = GenerateShaderParameter(storage_class, "", "");
  217. const std::vector<std::string> valid_storage_classes = {
  218. "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"};
  219. bool valid =
  220. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  221. storage_class) != valid_storage_classes.end();
  222. CompileSuccessfully(spirv);
  223. if (valid) {
  224. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  225. } else {
  226. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  227. if (storage_class == "StorageBuffer") {
  228. EXPECT_THAT(getDiagnosticString(),
  229. HasSubstr("StorageBuffer pointer operand '1[%p]' requires a "
  230. "variable pointers capability"));
  231. } else {
  232. EXPECT_THAT(
  233. getDiagnosticString(),
  234. HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
  235. }
  236. }
  237. }
  238. TEST_P(ValidateFunctionCall, ParameterVariablePointersStorageBuffer) {
  239. const std::string storage_class = GetParam();
  240. std::string spirv = GenerateShaderParameter(
  241. storage_class, "OpCapability VariablePointersStorageBuffer",
  242. "OpExtension \"SPV_KHR_variable_pointers\"");
  243. const std::vector<std::string> valid_storage_classes = {
  244. "UniformConstant", "Function", "Private",
  245. "Workgroup", "StorageBuffer", "AtomicCounter"};
  246. bool valid =
  247. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  248. storage_class) != valid_storage_classes.end();
  249. CompileSuccessfully(spirv);
  250. if (valid) {
  251. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  252. } else {
  253. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  254. EXPECT_THAT(getDiagnosticString(),
  255. HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
  256. }
  257. }
  258. TEST_P(ValidateFunctionCall, ParameterVariablePointers) {
  259. const std::string storage_class = GetParam();
  260. std::string spirv =
  261. GenerateShaderParameter(storage_class, "OpCapability VariablePointers",
  262. "OpExtension \"SPV_KHR_variable_pointers\"");
  263. const std::vector<std::string> valid_storage_classes = {
  264. "UniformConstant", "Function", "Private",
  265. "Workgroup", "StorageBuffer", "AtomicCounter"};
  266. bool valid =
  267. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  268. storage_class) != valid_storage_classes.end();
  269. CompileSuccessfully(spirv);
  270. if (valid) {
  271. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  272. } else {
  273. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  274. EXPECT_THAT(getDiagnosticString(),
  275. HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
  276. }
  277. }
  278. TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) {
  279. const std::string storage_class = GetParam();
  280. std::string spirv = GenerateShaderAccessChain(storage_class, "", "");
  281. const std::vector<std::string> valid_storage_classes = {
  282. "Function", "Private", "Workgroup", "AtomicCounter"};
  283. bool valid_sc =
  284. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  285. storage_class) != valid_storage_classes.end();
  286. CompileSuccessfully(spirv);
  287. spv_result_t expected_result =
  288. storage_class == "UniformConstant" ? SPV_SUCCESS : SPV_ERROR_INVALID_ID;
  289. EXPECT_EQ(expected_result, ValidateInstructions());
  290. if (valid_sc) {
  291. EXPECT_THAT(
  292. getDiagnosticString(),
  293. HasSubstr(
  294. "Pointer operand '2[%gep]' must be a memory object declaration"));
  295. } else {
  296. if (storage_class == "StorageBuffer") {
  297. EXPECT_THAT(
  298. getDiagnosticString(),
  299. HasSubstr("StorageBuffer pointer operand '2[%gep]' requires a "
  300. "variable pointers capability"));
  301. } else if (storage_class != "UniformConstant") {
  302. EXPECT_THAT(
  303. getDiagnosticString(),
  304. HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
  305. }
  306. }
  307. }
  308. TEST_P(ValidateFunctionCall,
  309. NonMemoryObjectDeclarationVariablePointersStorageBuffer) {
  310. const std::string storage_class = GetParam();
  311. std::string spirv = GenerateShaderAccessChain(
  312. storage_class, "OpCapability VariablePointersStorageBuffer",
  313. "OpExtension \"SPV_KHR_variable_pointers\"");
  314. const std::vector<std::string> valid_storage_classes = {
  315. "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
  316. bool valid_sc =
  317. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  318. storage_class) != valid_storage_classes.end();
  319. bool validate =
  320. storage_class == "StorageBuffer" || storage_class == "UniformConstant";
  321. CompileSuccessfully(spirv);
  322. if (validate) {
  323. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  324. } else {
  325. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  326. if (valid_sc) {
  327. EXPECT_THAT(
  328. getDiagnosticString(),
  329. HasSubstr(
  330. "Pointer operand '2[%gep]' must be a memory object declaration"));
  331. } else {
  332. EXPECT_THAT(
  333. getDiagnosticString(),
  334. HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
  335. }
  336. }
  337. }
  338. TEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationVariablePointers) {
  339. const std::string storage_class = GetParam();
  340. std::string spirv =
  341. GenerateShaderAccessChain(storage_class, "OpCapability VariablePointers",
  342. "OpExtension \"SPV_KHR_variable_pointers\"");
  343. const std::vector<std::string> valid_storage_classes = {
  344. "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
  345. bool valid_sc =
  346. std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
  347. storage_class) != valid_storage_classes.end();
  348. bool validate = storage_class == "StorageBuffer" ||
  349. storage_class == "Workgroup" ||
  350. storage_class == "UniformConstant";
  351. CompileSuccessfully(spirv);
  352. if (validate) {
  353. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  354. } else {
  355. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  356. if (valid_sc) {
  357. EXPECT_THAT(
  358. getDiagnosticString(),
  359. HasSubstr(
  360. "Pointer operand '2[%gep]' must be a memory object declaration"));
  361. } else {
  362. EXPECT_THAT(
  363. getDiagnosticString(),
  364. HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
  365. }
  366. }
  367. }
  368. TEST_F(ValidateFunctionCall, LogicallyMatchingPointers) {
  369. std::string spirv =
  370. R"(
  371. OpCapability Shader
  372. OpMemoryModel Logical GLSL450
  373. OpEntryPoint GLCompute %1 "main"
  374. OpExecutionMode %1 LocalSize 1 1 1
  375. OpSource HLSL 600
  376. OpDecorate %2 DescriptorSet 0
  377. OpDecorate %2 Binding 0
  378. OpMemberDecorate %_struct_3 0 Offset 0
  379. OpDecorate %_runtimearr__struct_3 ArrayStride 4
  380. OpMemberDecorate %_struct_5 0 Offset 0
  381. OpDecorate %_struct_5 BufferBlock
  382. %int = OpTypeInt 32 1
  383. %int_0 = OpConstant %int 0
  384. %uint = OpTypeInt 32 0
  385. %uint_0 = OpConstant %uint 0
  386. %_struct_3 = OpTypeStruct %int
  387. %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
  388. %_struct_5 = OpTypeStruct %_runtimearr__struct_3
  389. %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
  390. %void = OpTypeVoid
  391. %14 = OpTypeFunction %void
  392. %_struct_15 = OpTypeStruct %int
  393. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  394. %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
  395. %18 = OpTypeFunction %void %_ptr_Function__struct_15
  396. %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
  397. %1 = OpFunction %void None %14
  398. %19 = OpLabel
  399. %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
  400. %21 = OpFunctionCall %void %22 %20
  401. OpReturn
  402. OpFunctionEnd
  403. %22 = OpFunction %void None %18
  404. %23 = OpFunctionParameter %_ptr_Function__struct_15
  405. %24 = OpLabel
  406. OpReturn
  407. OpFunctionEnd
  408. )";
  409. CompileSuccessfully(spirv);
  410. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  411. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  412. }
  413. TEST_F(ValidateFunctionCall, LogicallyMatchingPointersNestedStruct) {
  414. std::string spirv =
  415. R"(
  416. OpCapability Shader
  417. OpMemoryModel Logical GLSL450
  418. OpEntryPoint GLCompute %1 "main"
  419. OpExecutionMode %1 LocalSize 1 1 1
  420. OpSource HLSL 600
  421. OpDecorate %2 DescriptorSet 0
  422. OpDecorate %2 Binding 0
  423. OpMemberDecorate %_struct_3 0 Offset 0
  424. OpMemberDecorate %_struct_4 0 Offset 0
  425. OpDecorate %_runtimearr__struct_4 ArrayStride 4
  426. OpMemberDecorate %_struct_6 0 Offset 0
  427. OpDecorate %_struct_6 BufferBlock
  428. %int = OpTypeInt 32 1
  429. %int_0 = OpConstant %int 0
  430. %uint = OpTypeInt 32 0
  431. %uint_0 = OpConstant %uint 0
  432. %_struct_3 = OpTypeStruct %int
  433. %_struct_4 = OpTypeStruct %_struct_3
  434. %_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4
  435. %_struct_6 = OpTypeStruct %_runtimearr__struct_4
  436. %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
  437. %void = OpTypeVoid
  438. %13 = OpTypeFunction %void
  439. %_struct_14 = OpTypeStruct %int
  440. %_struct_15 = OpTypeStruct %_struct_14
  441. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  442. %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
  443. %18 = OpTypeFunction %void %_ptr_Function__struct_15
  444. %2 = OpVariable %_ptr_Uniform__struct_6 Uniform
  445. %1 = OpFunction %void None %13
  446. %19 = OpLabel
  447. %20 = OpVariable %_ptr_Function__struct_15 Function
  448. %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0
  449. %22 = OpFunctionCall %void %23 %21
  450. OpReturn
  451. OpFunctionEnd
  452. %23 = OpFunction %void None %18
  453. %24 = OpFunctionParameter %_ptr_Function__struct_15
  454. %25 = OpLabel
  455. OpReturn
  456. OpFunctionEnd
  457. )";
  458. CompileSuccessfully(spirv);
  459. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  460. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  461. }
  462. TEST_F(ValidateFunctionCall, LogicallyMatchingPointersNestedArray) {
  463. std::string spirv =
  464. R"(
  465. OpCapability Shader
  466. OpMemoryModel Logical GLSL450
  467. OpEntryPoint GLCompute %1 "main"
  468. OpExecutionMode %1 LocalSize 1 1 1
  469. OpSource HLSL 600
  470. OpDecorate %2 DescriptorSet 0
  471. OpDecorate %2 Binding 0
  472. OpDecorate %_arr_int_uint_10 ArrayStride 4
  473. OpMemberDecorate %_struct_4 0 Offset 0
  474. OpDecorate %_runtimearr__struct_4 ArrayStride 40
  475. OpMemberDecorate %_struct_6 0 Offset 0
  476. OpDecorate %_struct_6 BufferBlock
  477. %int = OpTypeInt 32 1
  478. %int_0 = OpConstant %int 0
  479. %uint = OpTypeInt 32 0
  480. %uint_0 = OpConstant %uint 0
  481. %uint_10 = OpConstant %uint 10
  482. %_arr_int_uint_10 = OpTypeArray %int %uint_10
  483. %_struct_4 = OpTypeStruct %_arr_int_uint_10
  484. %_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4
  485. %_struct_6 = OpTypeStruct %_runtimearr__struct_4
  486. %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
  487. %void = OpTypeVoid
  488. %14 = OpTypeFunction %void
  489. %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
  490. %_arr_int_uint_10_0 = OpTypeArray %int %uint_10
  491. %_struct_17 = OpTypeStruct %_arr_int_uint_10_0
  492. %_ptr_Function__struct_17 = OpTypePointer Function %_struct_17
  493. %19 = OpTypeFunction %void %_ptr_Function__struct_17
  494. %2 = OpVariable %_ptr_Uniform__struct_6 Uniform
  495. %1 = OpFunction %void None %14
  496. %20 = OpLabel
  497. %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0
  498. %22 = OpFunctionCall %void %23 %21
  499. OpReturn
  500. OpFunctionEnd
  501. %23 = OpFunction %void None %19
  502. %24 = OpFunctionParameter %_ptr_Function__struct_17
  503. %25 = OpLabel
  504. OpReturn
  505. OpFunctionEnd
  506. )";
  507. CompileSuccessfully(spirv);
  508. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  509. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  510. }
  511. TEST_F(ValidateFunctionCall, LogicallyMismatchedPointersMissingMember) {
  512. // Validation should fail because the formal parameter type has two members,
  513. // while the actual parameter only has 1.
  514. std::string spirv =
  515. R"(
  516. OpCapability Shader
  517. OpMemoryModel Logical GLSL450
  518. OpEntryPoint GLCompute %1 "main"
  519. OpExecutionMode %1 LocalSize 1 1 1
  520. OpSource HLSL 600
  521. OpDecorate %2 DescriptorSet 0
  522. OpDecorate %2 Binding 0
  523. OpMemberDecorate %_struct_3 0 Offset 0
  524. OpDecorate %_runtimearr__struct_3 ArrayStride 4
  525. OpMemberDecorate %_struct_5 0 Offset 0
  526. OpDecorate %_struct_5 BufferBlock
  527. %int = OpTypeInt 32 1
  528. %int_0 = OpConstant %int 0
  529. %uint = OpTypeInt 32 0
  530. %uint_0 = OpConstant %uint 0
  531. %_struct_3 = OpTypeStruct %int
  532. %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
  533. %_struct_5 = OpTypeStruct %_runtimearr__struct_3
  534. %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
  535. %void = OpTypeVoid
  536. %14 = OpTypeFunction %void
  537. %_struct_15 = OpTypeStruct %int %int
  538. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  539. %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
  540. %18 = OpTypeFunction %void %_ptr_Function__struct_15
  541. %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
  542. %1 = OpFunction %void None %14
  543. %19 = OpLabel
  544. %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
  545. %21 = OpFunctionCall %void %22 %20
  546. OpReturn
  547. OpFunctionEnd
  548. %22 = OpFunction %void None %18
  549. %23 = OpFunctionParameter %_ptr_Function__struct_15
  550. %24 = OpLabel
  551. OpReturn
  552. OpFunctionEnd
  553. )";
  554. CompileSuccessfully(spirv);
  555. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  556. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  557. EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
  558. EXPECT_THAT(getDiagnosticString(),
  559. HasSubstr("type does not match Function <id>"));
  560. }
  561. TEST_F(ValidateFunctionCall, LogicallyMismatchedPointersDifferentMemberType) {
  562. // Validation should fail because the formal parameter has a member that is
  563. // a different type than the actual parameter.
  564. std::string spirv =
  565. R"(
  566. OpCapability Shader
  567. OpMemoryModel Logical GLSL450
  568. OpEntryPoint GLCompute %1 "main"
  569. OpExecutionMode %1 LocalSize 1 1 1
  570. OpSource HLSL 600
  571. OpDecorate %2 DescriptorSet 0
  572. OpDecorate %2 Binding 0
  573. OpMemberDecorate %_struct_3 0 Offset 0
  574. OpDecorate %_runtimearr__struct_3 ArrayStride 4
  575. OpMemberDecorate %_struct_5 0 Offset 0
  576. OpDecorate %_struct_5 BufferBlock
  577. %int = OpTypeInt 32 1
  578. %int_0 = OpConstant %int 0
  579. %uint = OpTypeInt 32 0
  580. %uint_0 = OpConstant %uint 0
  581. %_struct_3 = OpTypeStruct %uint
  582. %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
  583. %_struct_5 = OpTypeStruct %_runtimearr__struct_3
  584. %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
  585. %void = OpTypeVoid
  586. %14 = OpTypeFunction %void
  587. %_struct_15 = OpTypeStruct %int
  588. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  589. %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
  590. %18 = OpTypeFunction %void %_ptr_Function__struct_15
  591. %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
  592. %1 = OpFunction %void None %14
  593. %19 = OpLabel
  594. %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
  595. %21 = OpFunctionCall %void %22 %20
  596. OpReturn
  597. OpFunctionEnd
  598. %22 = OpFunction %void None %18
  599. %23 = OpFunctionParameter %_ptr_Function__struct_15
  600. %24 = OpLabel
  601. OpReturn
  602. OpFunctionEnd
  603. )";
  604. CompileSuccessfully(spirv);
  605. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  606. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  607. EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
  608. EXPECT_THAT(getDiagnosticString(),
  609. HasSubstr("type does not match Function <id>"));
  610. }
  611. TEST_F(ValidateFunctionCall,
  612. LogicallyMismatchedPointersIncompatableDecorations) {
  613. // Validation should fail because the formal parameter has an incompatible
  614. // decoration.
  615. std::string spirv =
  616. R"(
  617. OpCapability Shader
  618. OpMemoryModel Logical GLSL450
  619. OpEntryPoint GLCompute %1 "main"
  620. OpExecutionMode %1 LocalSize 1 1 1
  621. OpSource HLSL 600
  622. OpDecorate %2 DescriptorSet 0
  623. OpDecorate %2 Binding 0
  624. OpMemberDecorate %_struct_3 0 Offset 0
  625. OpDecorate %_runtimearr__struct_3 ArrayStride 4
  626. OpMemberDecorate %_struct_5 0 Offset 0
  627. OpDecorate %_struct_5 Block
  628. OpMemberDecorate %_struct_15 0 NonWritable
  629. %int = OpTypeInt 32 1
  630. %int_0 = OpConstant %int 0
  631. %uint = OpTypeInt 32 0
  632. %uint_0 = OpConstant %uint 0
  633. %_struct_3 = OpTypeStruct %int
  634. %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
  635. %_struct_5 = OpTypeStruct %_runtimearr__struct_3
  636. %_ptr_StorageBuffer__struct_5 = OpTypePointer StorageBuffer %_struct_5
  637. %void = OpTypeVoid
  638. %14 = OpTypeFunction %void
  639. %_struct_15 = OpTypeStruct %int
  640. %_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
  641. %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
  642. %18 = OpTypeFunction %void %_ptr_Function__struct_15
  643. %2 = OpVariable %_ptr_StorageBuffer__struct_5 StorageBuffer
  644. %1 = OpFunction %void None %14
  645. %19 = OpLabel
  646. %20 = OpAccessChain %_ptr_StorageBuffer__struct_3 %2 %int_0 %uint_0
  647. %21 = OpFunctionCall %void %22 %20
  648. OpReturn
  649. OpFunctionEnd
  650. %22 = OpFunction %void None %18
  651. %23 = OpFunctionParameter %_ptr_Function__struct_15
  652. %24 = OpLabel
  653. OpReturn
  654. OpFunctionEnd
  655. )";
  656. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  657. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  658. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  659. EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
  660. EXPECT_THAT(getDiagnosticString(),
  661. HasSubstr("type does not match Function <id>"));
  662. }
  663. TEST_F(ValidateFunctionCall,
  664. LogicallyMismatchedPointersIncompatableDecorations2) {
  665. // Validation should fail because the formal parameter has an incompatible
  666. // decoration.
  667. std::string spirv =
  668. R"(
  669. OpCapability Shader
  670. OpMemoryModel Logical GLSL450
  671. OpEntryPoint GLCompute %1 "main"
  672. OpExecutionMode %1 LocalSize 1 1 1
  673. OpSource HLSL 600
  674. OpDecorate %2 DescriptorSet 0
  675. OpDecorate %2 Binding 0
  676. OpMemberDecorate %_struct_3 0 Offset 0
  677. OpDecorate %_runtimearr__struct_3 ArrayStride 4
  678. OpMemberDecorate %_struct_5 0 Offset 0
  679. OpDecorate %_struct_5 BufferBlock
  680. OpDecorate %_ptr_Uniform__struct_3 ArrayStride 4
  681. OpDecorate %_ptr_Uniform__struct_3_0 ArrayStride 8
  682. %int = OpTypeInt 32 1
  683. %int_0 = OpConstant %int 0
  684. %uint = OpTypeInt 32 0
  685. %uint_0 = OpConstant %uint 0
  686. %_struct_3 = OpTypeStruct %int
  687. %_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
  688. %_struct_5 = OpTypeStruct %_runtimearr__struct_3
  689. %_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
  690. %void = OpTypeVoid
  691. %14 = OpTypeFunction %void
  692. %_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
  693. %_ptr_Uniform__struct_3_0 = OpTypePointer Uniform %_struct_3
  694. %18 = OpTypeFunction %void %_ptr_Uniform__struct_3_0
  695. %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
  696. %1 = OpFunction %void None %14
  697. %19 = OpLabel
  698. %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
  699. %21 = OpFunctionCall %void %22 %20
  700. OpReturn
  701. OpFunctionEnd
  702. %22 = OpFunction %void None %18
  703. %23 = OpFunctionParameter %_ptr_Uniform__struct_3_0
  704. %24 = OpLabel
  705. OpReturn
  706. OpFunctionEnd
  707. )";
  708. CompileSuccessfully(spirv);
  709. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  710. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  711. EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
  712. EXPECT_THAT(getDiagnosticString(),
  713. HasSubstr("type does not match Function <id>"));
  714. }
  715. TEST_F(ValidateFunctionCall, LogicallyMismatchedPointersArraySize) {
  716. // Validation should fail because the formal parameter array has a different
  717. // number of element than the actual parameter.
  718. std::string spirv =
  719. R"(
  720. OpCapability Shader
  721. OpMemoryModel Logical GLSL450
  722. OpEntryPoint GLCompute %1 "main"
  723. OpExecutionMode %1 LocalSize 1 1 1
  724. OpSource HLSL 600
  725. OpDecorate %2 DescriptorSet 0
  726. OpDecorate %2 Binding 0
  727. OpDecorate %_arr_int_uint_10 ArrayStride 4
  728. OpMemberDecorate %_struct_4 0 Offset 0
  729. OpDecorate %_runtimearr__struct_4 ArrayStride 40
  730. OpMemberDecorate %_struct_6 0 Offset 0
  731. OpDecorate %_struct_6 BufferBlock
  732. %int = OpTypeInt 32 1
  733. %int_0 = OpConstant %int 0
  734. %uint = OpTypeInt 32 0
  735. %uint_0 = OpConstant %uint 0
  736. %uint_5 = OpConstant %uint 5
  737. %uint_10 = OpConstant %uint 10
  738. %_arr_int_uint_10 = OpTypeArray %int %uint_10
  739. %_struct_4 = OpTypeStruct %_arr_int_uint_10
  740. %_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4
  741. %_struct_6 = OpTypeStruct %_runtimearr__struct_4
  742. %_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
  743. %void = OpTypeVoid
  744. %14 = OpTypeFunction %void
  745. %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
  746. %_arr_int_uint_5 = OpTypeArray %int %uint_5
  747. %_struct_17 = OpTypeStruct %_arr_int_uint_5
  748. %_ptr_Function__struct_17 = OpTypePointer Function %_struct_17
  749. %19 = OpTypeFunction %void %_ptr_Function__struct_17
  750. %2 = OpVariable %_ptr_Uniform__struct_6 Uniform
  751. %1 = OpFunction %void None %14
  752. %20 = OpLabel
  753. %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0
  754. %22 = OpFunctionCall %void %23 %21
  755. OpReturn
  756. OpFunctionEnd
  757. %23 = OpFunction %void None %19
  758. %24 = OpFunctionParameter %_ptr_Function__struct_17
  759. %25 = OpLabel
  760. OpReturn
  761. OpFunctionEnd
  762. )";
  763. CompileSuccessfully(spirv);
  764. spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
  765. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  766. EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
  767. EXPECT_THAT(getDiagnosticString(),
  768. HasSubstr("type does not match Function <id>"));
  769. }
  770. INSTANTIATE_TEST_SUITE_P(StorageClass, ValidateFunctionCall,
  771. Values("UniformConstant", "Input", "Uniform", "Output",
  772. "Workgroup", "Private", "Function",
  773. "PushConstant", "Image", "StorageBuffer",
  774. "AtomicCounter"));
  775. } // namespace
  776. } // namespace val
  777. } // namespace spvtools