val_function_test.cpp 34 KB

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