val_extensions_test.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. // Copyright (c) 2017 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. // Tests for OpExtension validator rules.
  15. #include <string>
  16. #include <vector>
  17. #include "gmock/gmock.h"
  18. #include "source/extensions.h"
  19. #include "source/spirv_target_env.h"
  20. #include "test/unit_spirv.h"
  21. #include "test/val/val_fixtures.h"
  22. namespace spvtools {
  23. namespace val {
  24. namespace {
  25. using ::testing::HasSubstr;
  26. using ::testing::Not;
  27. using ::testing::Values;
  28. using ::testing::ValuesIn;
  29. using ValidateKnownExtensions = spvtest::ValidateBase<std::string>;
  30. using ValidateUnknownExtensions = spvtest::ValidateBase<std::string>;
  31. using ValidateExtensionCapabilities = spvtest::ValidateBase<bool>;
  32. // Returns expected error string if |extension| is not recognized.
  33. std::string GetErrorString(const std::string& extension) {
  34. return "Found unrecognized extension " + extension;
  35. }
  36. INSTANTIATE_TEST_SUITE_P(
  37. ExpectSuccess, ValidateKnownExtensions,
  38. Values(
  39. // Match the order as published on the SPIR-V Registry.
  40. "SPV_AMD_shader_explicit_vertex_parameter",
  41. "SPV_AMD_shader_trinary_minmax", "SPV_AMD_gcn_shader",
  42. "SPV_KHR_shader_ballot", "SPV_AMD_shader_ballot",
  43. "SPV_AMD_gpu_shader_half_float", "SPV_KHR_shader_draw_parameters",
  44. "SPV_KHR_subgroup_vote", "SPV_KHR_16bit_storage",
  45. "SPV_KHR_device_group", "SPV_KHR_multiview",
  46. "SPV_NVX_multiview_per_view_attributes", "SPV_NV_viewport_array2",
  47. "SPV_NV_stereo_view_rendering", "SPV_NV_sample_mask_override_coverage",
  48. "SPV_NV_geometry_shader_passthrough", "SPV_AMD_texture_gather_bias_lod",
  49. "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_variable_pointers",
  50. "SPV_AMD_gpu_shader_int16", "SPV_KHR_post_depth_coverage",
  51. "SPV_KHR_shader_atomic_counter_ops", "SPV_EXT_shader_stencil_export",
  52. "SPV_EXT_shader_viewport_index_layer",
  53. "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_fragment_mask",
  54. "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1",
  55. "SPV_NV_shader_subgroup_partitioned", "SPV_EXT_descriptor_indexing",
  56. "SPV_KHR_terminate_invocation",
  57. "SPV_KHR_relaxed_extended_instruction"));
  58. INSTANTIATE_TEST_SUITE_P(FailSilently, ValidateUnknownExtensions,
  59. Values("ERROR_unknown_extension", "SPV_KHR_",
  60. "SPV_KHR_shader_ballot_ERROR"));
  61. TEST_P(ValidateKnownExtensions, ExpectSuccess) {
  62. const std::string extension = GetParam();
  63. const std::string str =
  64. "OpCapability Shader\nOpCapability Linkage\nOpExtension \"" + extension +
  65. "\"\nOpMemoryModel Logical GLSL450";
  66. CompileSuccessfully(str.c_str());
  67. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  68. EXPECT_THAT(getDiagnosticString(), Not(HasSubstr(GetErrorString(extension))));
  69. }
  70. TEST_P(ValidateUnknownExtensions, FailSilently) {
  71. const std::string extension = GetParam();
  72. const std::string str =
  73. "OpCapability Shader\nOpCapability Linkage\nOpExtension \"" + extension +
  74. "\"\nOpMemoryModel Logical GLSL450";
  75. CompileSuccessfully(str.c_str());
  76. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  77. EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(extension)));
  78. }
  79. TEST_F(ValidateUnknownExtensions, HitMaxNumOfWarnings) {
  80. const std::string str =
  81. std::string("OpCapability Shader\n") + "OpCapability Linkage\n" +
  82. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  83. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  84. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  85. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  86. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  87. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  88. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  89. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  90. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  91. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  92. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  93. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  94. "OpExtension \"bad_ext\"\n" + "OpExtension \"bad_ext\"\n" +
  95. "OpMemoryModel Logical GLSL450";
  96. CompileSuccessfully(str.c_str());
  97. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  98. EXPECT_THAT(getDiagnosticString(),
  99. HasSubstr("Other warnings have been suppressed."));
  100. }
  101. TEST_F(ValidateExtensionCapabilities, DeclCapabilitySuccess) {
  102. const std::string str =
  103. "OpCapability Shader\nOpCapability Linkage\nOpCapability DeviceGroup\n"
  104. "OpExtension \"SPV_KHR_device_group\""
  105. "\nOpMemoryModel Logical GLSL450";
  106. CompileSuccessfully(str.c_str());
  107. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
  108. }
  109. TEST_F(ValidateExtensionCapabilities, DeclCapabilityFailure) {
  110. const std::string str =
  111. "OpCapability Shader\nOpCapability Linkage\nOpCapability DeviceGroup\n"
  112. "\nOpMemoryModel Logical GLSL450";
  113. CompileSuccessfully(str.c_str());
  114. ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
  115. EXPECT_THAT(getDiagnosticString(), HasSubstr("1st operand of Capability"));
  116. EXPECT_THAT(getDiagnosticString(),
  117. HasSubstr("requires one of these extensions"));
  118. EXPECT_THAT(getDiagnosticString(), HasSubstr("SPV_KHR_device_group"));
  119. }
  120. TEST_F(ValidateExtensionCapabilities,
  121. DeclCapabilityFailureBlockMatchWIndowSAD) {
  122. const std::string str = R"(
  123. OpCapability Shader
  124. OpCapability TextureBlockMatch2QCOM
  125. OpExtension "SPV_QCOM_image_processing2"
  126. %1 = OpExtInstImport "GLSL.std.450"
  127. OpMemoryModel Logical GLSL450
  128. OpEntryPoint Fragment %main "main" %v_texcoord %fragColor %target_samp %ref_samp
  129. OpExecutionMode %main OriginUpperLeft
  130. OpSource GLSL 450
  131. OpSourceExtension "GL_QCOM_image_processing"
  132. OpSourceExtension "GL_QCOM_image_processing2"
  133. OpName %main "main"
  134. OpName %tgt_coords "tgt_coords"
  135. OpName %v_texcoord "v_texcoord"
  136. OpName %ref_coords "ref_coords"
  137. OpName %blockSize "blockSize"
  138. OpName %fragColor "fragColor"
  139. OpName %target_samp "target_samp"
  140. OpName %ref_samp "ref_samp"
  141. OpDecorate %v_texcoord Location 0
  142. OpDecorate %fragColor Location 0
  143. OpDecorate %target_samp DescriptorSet 0
  144. OpDecorate %target_samp Binding 4
  145. OpDecorate %ref_samp DescriptorSet 0
  146. OpDecorate %ref_samp Binding 5
  147. OpDecorate %target_samp BlockMatchTextureQCOM
  148. OpDecorate %target_samp BlockMatchSamplerQCOM
  149. OpDecorate %ref_samp BlockMatchTextureQCOM
  150. OpDecorate %ref_samp BlockMatchSamplerQCOM
  151. %void = OpTypeVoid
  152. %3 = OpTypeFunction %void
  153. %uint = OpTypeInt 32 0
  154. %v2uint = OpTypeVector %uint 2
  155. %_ptr_Function_v2uint = OpTypePointer Function %v2uint
  156. %float = OpTypeFloat 32
  157. %v4float = OpTypeVector %float 4
  158. %_ptr_Input_v4float = OpTypePointer Input %v4float
  159. %v_texcoord = OpVariable %_ptr_Input_v4float Input
  160. %uint_0 = OpConstant %uint 0
  161. %_ptr_Input_float = OpTypePointer Input %float
  162. %_ptr_Function_uint = OpTypePointer Function %uint
  163. %uint_1 = OpConstant %uint 1
  164. %uint_2 = OpConstant %uint 2
  165. %uint_3 = OpConstant %uint 3
  166. %uint_4 = OpConstant %uint 4
  167. %39 = OpConstantComposite %v2uint %uint_4 %uint_4
  168. %_ptr_Output_v4float = OpTypePointer Output %v4float
  169. %fragColor = OpVariable %_ptr_Output_v4float Output
  170. %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
  171. %43 = OpTypeSampledImage %42
  172. %_ptr_UniformConstant_43 = OpTypePointer UniformConstant %43
  173. %target_samp = OpVariable %_ptr_UniformConstant_43 UniformConstant
  174. %ref_samp = OpVariable %_ptr_UniformConstant_43 UniformConstant
  175. %main = OpFunction %void None %3
  176. %5 = OpLabel
  177. %tgt_coords = OpVariable %_ptr_Function_v2uint Function
  178. %ref_coords = OpVariable %_ptr_Function_v2uint Function
  179. %blockSize = OpVariable %_ptr_Function_v2uint Function
  180. %16 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_0
  181. %17 = OpLoad %float %16
  182. %18 = OpConvertFToU %uint %17
  183. %20 = OpAccessChain %_ptr_Function_uint %tgt_coords %uint_0
  184. OpStore %20 %18
  185. %22 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_1
  186. %23 = OpLoad %float %22
  187. %24 = OpConvertFToU %uint %23
  188. %25 = OpAccessChain %_ptr_Function_uint %tgt_coords %uint_0
  189. OpStore %25 %24
  190. %28 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_2
  191. %29 = OpLoad %float %28
  192. %30 = OpConvertFToU %uint %29
  193. %31 = OpAccessChain %_ptr_Function_uint %ref_coords %uint_0
  194. OpStore %31 %30
  195. %33 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_3
  196. %34 = OpLoad %float %33
  197. %35 = OpConvertFToU %uint %34
  198. %36 = OpAccessChain %_ptr_Function_uint %ref_coords %uint_1
  199. OpStore %36 %35
  200. OpStore %blockSize %39
  201. %46 = OpLoad %43 %target_samp
  202. %47 = OpLoad %v2uint %tgt_coords
  203. %49 = OpLoad %43 %ref_samp
  204. %50 = OpLoad %v2uint %ref_coords
  205. %51 = OpLoad %v2uint %blockSize
  206. %52 = OpImageBlockMatchWindowSADQCOM %v4float %46 %47 %49 %50 %51
  207. OpStore %fragColor %52
  208. OpReturn
  209. OpFunctionEnd
  210. )";
  211. CompileSuccessfully(str.c_str());
  212. ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
  213. EXPECT_THAT(getDiagnosticString(), HasSubstr("2nd operand of Decorate"));
  214. EXPECT_THAT(getDiagnosticString(),
  215. HasSubstr("requires one of these extensions"));
  216. EXPECT_THAT(getDiagnosticString(), HasSubstr("SPV_QCOM_image_processing"));
  217. }
  218. TEST_F(ValidateExtensionCapabilities,
  219. DeclCapabilityFailureBlockMatchWIndowSSD) {
  220. const std::string str = R"(
  221. OpCapability Shader
  222. OpCapability TextureBlockMatch2QCOM
  223. OpExtension "SPV_QCOM_image_processing2"
  224. %1 = OpExtInstImport "GLSL.std.450"
  225. OpMemoryModel Logical GLSL450
  226. OpEntryPoint Fragment %main "main" %v_texcoord %fragColor %tex2D_src1 %samp %tex2D_src2
  227. OpExecutionMode %main OriginUpperLeft
  228. OpSource GLSL 450
  229. OpSourceExtension "GL_QCOM_image_processing"
  230. OpSourceExtension "GL_QCOM_image_processing2"
  231. OpName %main "main"
  232. OpName %tgt_coords "tgt_coords"
  233. OpName %v_texcoord "v_texcoord"
  234. OpName %ref_coords "ref_coords"
  235. OpName %blockSize "blockSize"
  236. OpName %fragColor "fragColor"
  237. OpName %tex2D_src1 "tex2D_src1"
  238. OpName %samp "samp"
  239. OpName %tex2D_src2 "tex2D_src2"
  240. OpDecorate %v_texcoord Location 0
  241. OpDecorate %fragColor Location 0
  242. OpDecorate %tex2D_src1 DescriptorSet 0
  243. OpDecorate %tex2D_src1 Binding 1
  244. OpDecorate %samp DescriptorSet 0
  245. OpDecorate %samp Binding 3
  246. OpDecorate %tex2D_src2 DescriptorSet 0
  247. OpDecorate %tex2D_src2 Binding 2
  248. OpDecorate %tex2D_src1 BlockMatchTextureQCOM
  249. OpDecorate %samp BlockMatchSamplerQCOM
  250. OpDecorate %tex2D_src2 BlockMatchTextureQCOM
  251. OpDecorate %samp BlockMatchSamplerQCOM
  252. %void = OpTypeVoid
  253. %3 = OpTypeFunction %void
  254. %uint = OpTypeInt 32 0
  255. %v2uint = OpTypeVector %uint 2
  256. %_ptr_Function_v2uint = OpTypePointer Function %v2uint
  257. %float = OpTypeFloat 32
  258. %v4float = OpTypeVector %float 4
  259. %_ptr_Input_v4float = OpTypePointer Input %v4float
  260. %v_texcoord = OpVariable %_ptr_Input_v4float Input
  261. %uint_0 = OpConstant %uint 0
  262. %_ptr_Input_float = OpTypePointer Input %float
  263. %_ptr_Function_uint = OpTypePointer Function %uint
  264. %uint_1 = OpConstant %uint 1
  265. %uint_2 = OpConstant %uint 2
  266. %uint_3 = OpConstant %uint 3
  267. %uint_4 = OpConstant %uint 4
  268. %39 = OpConstantComposite %v2uint %uint_4 %uint_4
  269. %_ptr_Output_v4float = OpTypePointer Output %v4float
  270. %fragColor = OpVariable %_ptr_Output_v4float Output
  271. %42 = OpTypeImage %float 2D 0 0 0 1 Unknown
  272. %_ptr_UniformConstant_42 = OpTypePointer UniformConstant %42
  273. %tex2D_src1 = OpVariable %_ptr_UniformConstant_42 UniformConstant
  274. %46 = OpTypeSampler
  275. %_ptr_UniformConstant_46 = OpTypePointer UniformConstant %46
  276. %samp = OpVariable %_ptr_UniformConstant_46 UniformConstant
  277. %50 = OpTypeSampledImage %42
  278. %tex2D_src2 = OpVariable %_ptr_UniformConstant_42 UniformConstant
  279. %main = OpFunction %void None %3
  280. %5 = OpLabel
  281. %tgt_coords = OpVariable %_ptr_Function_v2uint Function
  282. %ref_coords = OpVariable %_ptr_Function_v2uint Function
  283. %blockSize = OpVariable %_ptr_Function_v2uint Function
  284. %16 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_0
  285. %17 = OpLoad %float %16
  286. %18 = OpConvertFToU %uint %17
  287. %20 = OpAccessChain %_ptr_Function_uint %tgt_coords %uint_0
  288. OpStore %20 %18
  289. %22 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_1
  290. %23 = OpLoad %float %22
  291. %24 = OpConvertFToU %uint %23
  292. %25 = OpAccessChain %_ptr_Function_uint %tgt_coords %uint_0
  293. OpStore %25 %24
  294. %28 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_2
  295. %29 = OpLoad %float %28
  296. %30 = OpConvertFToU %uint %29
  297. %31 = OpAccessChain %_ptr_Function_uint %ref_coords %uint_0
  298. OpStore %31 %30
  299. %33 = OpAccessChain %_ptr_Input_float %v_texcoord %uint_3
  300. %34 = OpLoad %float %33
  301. %35 = OpConvertFToU %uint %34
  302. %36 = OpAccessChain %_ptr_Function_uint %ref_coords %uint_1
  303. OpStore %36 %35
  304. OpStore %blockSize %39
  305. %45 = OpLoad %42 %tex2D_src1
  306. %49 = OpLoad %46 %samp
  307. %51 = OpSampledImage %50 %45 %49
  308. %52 = OpLoad %v2uint %tgt_coords
  309. %54 = OpLoad %42 %tex2D_src2
  310. %55 = OpLoad %46 %samp
  311. %56 = OpSampledImage %50 %54 %55
  312. %57 = OpLoad %v2uint %ref_coords
  313. %58 = OpLoad %v2uint %blockSize
  314. %59 = OpImageBlockMatchWindowSSDQCOM %v4float %51 %52 %56 %57 %58
  315. OpStore %fragColor %59
  316. OpReturn
  317. OpFunctionEnd
  318. )";
  319. CompileSuccessfully(str.c_str());
  320. ASSERT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
  321. EXPECT_THAT(getDiagnosticString(), HasSubstr("2nd operand of Decorate"));
  322. EXPECT_THAT(getDiagnosticString(),
  323. HasSubstr("requires one of these extensions"));
  324. EXPECT_THAT(getDiagnosticString(), HasSubstr("SPV_QCOM_image_processing"));
  325. }
  326. using ValidateAMDShaderBallotCapabilities = spvtest::ValidateBase<std::string>;
  327. // Returns a vector of strings for the prefix of a SPIR-V assembly shader
  328. // that can use the group instructions introduced by SPV_AMD_shader_ballot.
  329. std::vector<std::string> ShaderPartsForAMDShaderBallot() {
  330. return std::vector<std::string>{R"(
  331. OpCapability Shader
  332. OpCapability Linkage
  333. )",
  334. R"(
  335. OpMemoryModel Logical GLSL450
  336. %float = OpTypeFloat 32
  337. %uint = OpTypeInt 32 0
  338. %int = OpTypeInt 32 1
  339. %scope = OpConstant %uint 3
  340. %uint_const = OpConstant %uint 42
  341. %int_const = OpConstant %uint 45
  342. %float_const = OpConstant %float 3.5
  343. %void = OpTypeVoid
  344. %fn_ty = OpTypeFunction %void
  345. %fn = OpFunction %void None %fn_ty
  346. %entry = OpLabel
  347. )"};
  348. }
  349. // Returns a list of SPIR-V assembly strings, where each uses only types
  350. // and IDs that can fit with a shader made from parts from the result
  351. // of ShaderPartsForAMDShaderBallot.
  352. std::vector<std::string> AMDShaderBallotGroupInstructions() {
  353. return std::vector<std::string>{
  354. "%iadd_reduce = OpGroupIAddNonUniformAMD %uint %scope Reduce %uint_const",
  355. "%iadd_iscan = OpGroupIAddNonUniformAMD %uint %scope InclusiveScan "
  356. "%uint_const",
  357. "%iadd_escan = OpGroupIAddNonUniformAMD %uint %scope ExclusiveScan "
  358. "%uint_const",
  359. "%fadd_reduce = OpGroupFAddNonUniformAMD %float %scope Reduce "
  360. "%float_const",
  361. "%fadd_iscan = OpGroupFAddNonUniformAMD %float %scope InclusiveScan "
  362. "%float_const",
  363. "%fadd_escan = OpGroupFAddNonUniformAMD %float %scope ExclusiveScan "
  364. "%float_const",
  365. "%fmin_reduce = OpGroupFMinNonUniformAMD %float %scope Reduce "
  366. "%float_const",
  367. "%fmin_iscan = OpGroupFMinNonUniformAMD %float %scope InclusiveScan "
  368. "%float_const",
  369. "%fmin_escan = OpGroupFMinNonUniformAMD %float %scope ExclusiveScan "
  370. "%float_const",
  371. "%umin_reduce = OpGroupUMinNonUniformAMD %uint %scope Reduce %uint_const",
  372. "%umin_iscan = OpGroupUMinNonUniformAMD %uint %scope InclusiveScan "
  373. "%uint_const",
  374. "%umin_escan = OpGroupUMinNonUniformAMD %uint %scope ExclusiveScan "
  375. "%uint_const",
  376. "%smin_reduce = OpGroupUMinNonUniformAMD %int %scope Reduce %int_const",
  377. "%smin_iscan = OpGroupUMinNonUniformAMD %int %scope InclusiveScan "
  378. "%int_const",
  379. "%smin_escan = OpGroupUMinNonUniformAMD %int %scope ExclusiveScan "
  380. "%int_const",
  381. "%fmax_reduce = OpGroupFMaxNonUniformAMD %float %scope Reduce "
  382. "%float_const",
  383. "%fmax_iscan = OpGroupFMaxNonUniformAMD %float %scope InclusiveScan "
  384. "%float_const",
  385. "%fmax_escan = OpGroupFMaxNonUniformAMD %float %scope ExclusiveScan "
  386. "%float_const",
  387. "%umax_reduce = OpGroupUMaxNonUniformAMD %uint %scope Reduce %uint_const",
  388. "%umax_iscan = OpGroupUMaxNonUniformAMD %uint %scope InclusiveScan "
  389. "%uint_const",
  390. "%umax_escan = OpGroupUMaxNonUniformAMD %uint %scope ExclusiveScan "
  391. "%uint_const",
  392. "%smax_reduce = OpGroupUMaxNonUniformAMD %int %scope Reduce %int_const",
  393. "%smax_iscan = OpGroupUMaxNonUniformAMD %int %scope InclusiveScan "
  394. "%int_const",
  395. "%smax_escan = OpGroupUMaxNonUniformAMD %int %scope ExclusiveScan "
  396. "%int_const"};
  397. }
  398. TEST_P(ValidateAMDShaderBallotCapabilities, ExpectSuccess) {
  399. // Succeed because the module specifies the SPV_AMD_shader_ballot extension.
  400. auto parts = ShaderPartsForAMDShaderBallot();
  401. const std::string assembly =
  402. parts[0] + "OpExtension \"SPV_AMD_shader_ballot\"\n" + parts[1] +
  403. GetParam() + "\nOpReturn OpFunctionEnd";
  404. CompileSuccessfully(assembly.c_str());
  405. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
  406. }
  407. INSTANTIATE_TEST_SUITE_P(ExpectSuccess, ValidateAMDShaderBallotCapabilities,
  408. ValuesIn(AMDShaderBallotGroupInstructions()));
  409. TEST_P(ValidateAMDShaderBallotCapabilities, ExpectFailure) {
  410. // Fail because the module does not specify the SPV_AMD_shader_ballot
  411. // extension.
  412. auto parts = ShaderPartsForAMDShaderBallot();
  413. const std::string assembly =
  414. parts[0] + parts[1] + GetParam() + "\nOpReturn OpFunctionEnd";
  415. CompileSuccessfully(assembly.c_str());
  416. EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY, ValidateInstructions());
  417. // Make sure we get an appropriate error message.
  418. // Find just the opcode name, skipping over the "Op" part.
  419. auto prefix_with_opcode = GetParam().substr(GetParam().find("Group"));
  420. auto opcode = prefix_with_opcode.substr(0, prefix_with_opcode.find(' '));
  421. EXPECT_THAT(
  422. getDiagnosticString(),
  423. HasSubstr(std::string("Opcode " + opcode +
  424. " requires one of these capabilities: Groups")));
  425. }
  426. INSTANTIATE_TEST_SUITE_P(ExpectFailure, ValidateAMDShaderBallotCapabilities,
  427. ValuesIn(AMDShaderBallotGroupInstructions()));
  428. struct ExtIntoCoreCase {
  429. const char* ext;
  430. const char* cap;
  431. const char* builtin;
  432. spv_target_env env;
  433. bool success;
  434. };
  435. using ValidateExtIntoCore = spvtest::ValidateBase<ExtIntoCoreCase>;
  436. // Make sure that we don't panic about missing extensions for using
  437. // functionalities that introduced in extensions but became core SPIR-V later.
  438. TEST_P(ValidateExtIntoCore, DoNotAskForExtensionInLaterVersion) {
  439. const std::string code = std::string(R"(
  440. OpCapability Shader
  441. OpCapability )") +
  442. GetParam().cap + R"(
  443. OpMemoryModel Logical GLSL450
  444. OpEntryPoint Vertex %main "main" %builtin
  445. OpDecorate %builtin BuiltIn )" + GetParam().builtin + R"(
  446. %void = OpTypeVoid
  447. %3 = OpTypeFunction %void
  448. %int = OpTypeInt 32 1
  449. %_ptr_Input_int = OpTypePointer Input %int
  450. %builtin = OpVariable %_ptr_Input_int Input
  451. %main = OpFunction %void None %3
  452. %5 = OpLabel
  453. %18 = OpLoad %int %builtin
  454. OpReturn
  455. OpFunctionEnd)";
  456. CompileSuccessfully(code.c_str(), GetParam().env);
  457. if (GetParam().success) {
  458. ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(GetParam().env))
  459. << getDiagnosticString();
  460. } else {
  461. ASSERT_NE(SPV_SUCCESS, ValidateInstructions(GetParam().env))
  462. << " in " << spvTargetEnvDescription(GetParam().env) << ":\n"
  463. << code;
  464. const std::string message = getDiagnosticString();
  465. if (spvIsVulkanEnv(GetParam().env)) {
  466. EXPECT_THAT(message, HasSubstr(std::string(GetParam().cap) +
  467. " is not allowed by Vulkan"));
  468. EXPECT_THAT(message, HasSubstr(std::string("or requires extension")));
  469. } else {
  470. EXPECT_THAT(message,
  471. HasSubstr(std::string("requires one of these extensions: ") +
  472. GetParam().ext));
  473. }
  474. }
  475. }
  476. // clang-format off
  477. INSTANTIATE_TEST_SUITE_P(
  478. KHR_extensions, ValidateExtIntoCore,
  479. ValuesIn(std::vector<ExtIntoCoreCase>{
  480. // SPV_KHR_shader_draw_parameters became core SPIR-V 1.3
  481. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_3, true},
  482. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_2, false},
  483. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_1, false},
  484. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_UNIVERSAL_1_0, false},
  485. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_VULKAN_1_1, true},
  486. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseVertex", SPV_ENV_VULKAN_1_0, false},
  487. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseInstance", SPV_ENV_UNIVERSAL_1_3, true},
  488. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "BaseInstance", SPV_ENV_VULKAN_1_0, false},
  489. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "DrawIndex", SPV_ENV_UNIVERSAL_1_3, true},
  490. {"SPV_KHR_shader_draw_parameters", "DrawParameters", "DrawIndex", SPV_ENV_UNIVERSAL_1_1, false},
  491. // SPV_KHR_multiview became core SPIR-V 1.3
  492. {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_3, true},
  493. {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_2, false},
  494. {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_1, false},
  495. {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_UNIVERSAL_1_0, false},
  496. {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_VULKAN_1_1, true},
  497. {"SPV_KHR_multiview", "MultiView", "ViewIndex", SPV_ENV_VULKAN_1_0, false},
  498. // SPV_KHR_device_group became core SPIR-V 1.3
  499. {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_3, true},
  500. {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_2, false},
  501. {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_1, false},
  502. {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_UNIVERSAL_1_0, false},
  503. {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_VULKAN_1_1, true},
  504. {"SPV_KHR_device_group", "DeviceGroup", "DeviceIndex", SPV_ENV_VULKAN_1_0, false},
  505. }));
  506. // clang-format on
  507. using ValidateRelaxedExtendedInstructionExt = spvtest::ValidateBase<bool>;
  508. TEST_F(ValidateRelaxedExtendedInstructionExt, RequiresExtension) {
  509. const std::string str = R"(
  510. OpCapability Shader
  511. OpExtension "SPV_KHR_non_semantic_info"
  512. %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
  513. OpMemoryModel Logical GLSL450
  514. OpEntryPoint GLCompute %2 "main"
  515. OpExecutionMode %2 LocalSize 1 1 1
  516. %3 = OpString "sample"
  517. %void = OpTypeVoid
  518. %uint = OpTypeInt 32 0
  519. %uint_0 = OpConstant %uint 0
  520. %7 = OpTypeFunction %void
  521. %8 = OpExtInst %void %1 DebugSource %3 %3
  522. %9 = OpExtInst %void %1 DebugCompilationUnit %uint_0 %uint_0 %8 %uint_0
  523. %10 = OpExtInstWithForwardRefsKHR %void %1 DebugTypeFunction %uint_0 %11
  524. %12 = OpExtInstWithForwardRefsKHR %void %1 DebugFunction %3 %10 %8 %uint_0 %uint_0 %11 %3 %uint_0 %uint_0
  525. %11 = OpExtInst %void %1 DebugTypeComposite %3 %uint_0 %8 %uint_0 %uint_0 %9 %3 %uint_0 %uint_0 %12
  526. %2 = OpFunction %void None %7
  527. %13 = OpLabel
  528. OpReturn
  529. OpFunctionEnd
  530. )";
  531. CompileSuccessfully(str.c_str());
  532. EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
  533. EXPECT_THAT(
  534. getDiagnosticString(),
  535. HasSubstr(
  536. "ExtInstWithForwardRefsKHR requires one of the following extensions:"
  537. " SPV_KHR_relaxed_extended_instruction \n"
  538. " %10 = OpExtInstWithForwardRefsKHR %void %1 DebugTypeFunction "
  539. "%uint_0 "
  540. "%11\n"));
  541. }
  542. } // namespace
  543. } // namespace val
  544. } // namespace spvtools