val_modes_test.cpp 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148
  1. // Copyright (c) 2018 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 <vector>
  17. #include "gmock/gmock.h"
  18. #include "source/spirv_target_env.h"
  19. #include "test/test_fixture.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::Combine;
  26. using ::testing::HasSubstr;
  27. using ::testing::Values;
  28. using ::testing::ValuesIn;
  29. using ValidateMode = spvtest::ValidateBase<bool>;
  30. const std::string kVoidFunction = R"(%void = OpTypeVoid
  31. %void_fn = OpTypeFunction %void
  32. %main = OpFunction %void None %void_fn
  33. %entry = OpLabel
  34. OpReturn
  35. OpFunctionEnd
  36. )";
  37. TEST_F(ValidateMode, GLComputeNoMode) {
  38. const std::string spirv = R"(
  39. OpCapability Shader
  40. OpMemoryModel Logical GLSL450
  41. OpEntryPoint GLCompute %main "main"
  42. )" + kVoidFunction;
  43. CompileSuccessfully(spirv);
  44. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  45. }
  46. TEST_F(ValidateMode, GLComputeNoModeVulkan) {
  47. const std::string spirv = R"(
  48. OpCapability Shader
  49. OpMemoryModel Logical GLSL450
  50. OpEntryPoint GLCompute %main "main"
  51. )" + kVoidFunction;
  52. spv_target_env env = SPV_ENV_VULKAN_1_0;
  53. CompileSuccessfully(spirv, env);
  54. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  55. EXPECT_THAT(getDiagnosticString(),
  56. AnyVUID("VUID-StandaloneSpirv-LocalSize-04683"));
  57. EXPECT_THAT(
  58. getDiagnosticString(),
  59. HasSubstr("In the Vulkan environment, GLCompute execution model entry "
  60. "points require either the LocalSize execution mode or an "
  61. "object decorated with WorkgroupSize must be specified."));
  62. }
  63. TEST_F(ValidateMode, GLComputeNoModeVulkanWorkgroupSize) {
  64. const std::string spirv = R"(
  65. OpCapability Shader
  66. OpMemoryModel Logical GLSL450
  67. OpEntryPoint GLCompute %main "main"
  68. OpDecorate %int3_1 BuiltIn WorkgroupSize
  69. %int = OpTypeInt 32 0
  70. %int3 = OpTypeVector %int 3
  71. %int_1 = OpConstant %int 1
  72. %int3_1 = OpConstantComposite %int3 %int_1 %int_1 %int_1
  73. )" + kVoidFunction;
  74. spv_target_env env = SPV_ENV_VULKAN_1_0;
  75. CompileSuccessfully(spirv, env);
  76. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  77. }
  78. TEST_F(ValidateMode, GLComputeVulkanLocalSize) {
  79. const std::string spirv = R"(
  80. OpCapability Shader
  81. OpMemoryModel Logical GLSL450
  82. OpEntryPoint GLCompute %main "main"
  83. OpExecutionMode %main LocalSize 1 1 1
  84. )" + kVoidFunction;
  85. spv_target_env env = SPV_ENV_VULKAN_1_0;
  86. CompileSuccessfully(spirv, env);
  87. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  88. }
  89. TEST_F(ValidateMode, FragmentOriginLowerLeftVulkan) {
  90. const std::string spirv = R"(
  91. OpCapability Shader
  92. OpMemoryModel Logical GLSL450
  93. OpEntryPoint Fragment %main "main"
  94. OpExecutionMode %main OriginLowerLeft
  95. )" + kVoidFunction;
  96. spv_target_env env = SPV_ENV_VULKAN_1_0;
  97. CompileSuccessfully(spirv, env);
  98. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  99. EXPECT_THAT(getDiagnosticString(),
  100. AnyVUID("VUID-StandaloneSpirv-OriginLowerLeft-04653"));
  101. EXPECT_THAT(getDiagnosticString(),
  102. HasSubstr("In the Vulkan environment, the OriginLowerLeft "
  103. "execution mode must not be used."));
  104. }
  105. TEST_F(ValidateMode, FragmentPixelCenterIntegerVulkan) {
  106. const std::string spirv = R"(
  107. OpCapability Shader
  108. OpMemoryModel Logical GLSL450
  109. OpEntryPoint Fragment %main "main"
  110. OpExecutionMode %main OriginUpperLeft
  111. OpExecutionMode %main PixelCenterInteger
  112. )" + kVoidFunction;
  113. spv_target_env env = SPV_ENV_VULKAN_1_0;
  114. CompileSuccessfully(spirv, env);
  115. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  116. EXPECT_THAT(getDiagnosticString(),
  117. AnyVUID("VUID-StandaloneSpirv-PixelCenterInteger-04654"));
  118. EXPECT_THAT(getDiagnosticString(),
  119. HasSubstr("In the Vulkan environment, the PixelCenterInteger "
  120. "execution mode must not be used."));
  121. }
  122. TEST_F(ValidateMode, GeometryNoOutputMode) {
  123. const std::string spirv = R"(
  124. OpCapability Geometry
  125. OpMemoryModel Logical GLSL450
  126. OpEntryPoint Geometry %main "main"
  127. OpExecutionMode %main InputPoints
  128. )" + kVoidFunction;
  129. CompileSuccessfully(spirv);
  130. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  131. EXPECT_THAT(getDiagnosticString(),
  132. HasSubstr("Geometry execution model entry points must specify "
  133. "exactly one of OutputPoints, OutputLineStrip or "
  134. "OutputTriangleStrip execution modes."));
  135. }
  136. TEST_F(ValidateMode, GeometryNoInputMode) {
  137. const std::string spirv = R"(
  138. OpCapability Geometry
  139. OpMemoryModel Logical GLSL450
  140. OpEntryPoint Geometry %main "main"
  141. OpExecutionMode %main OutputPoints
  142. )" + kVoidFunction;
  143. CompileSuccessfully(spirv);
  144. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  145. EXPECT_THAT(
  146. getDiagnosticString(),
  147. HasSubstr("Geometry execution model entry points must specify exactly "
  148. "one of InputPoints, InputLines, InputLinesAdjacency, "
  149. "Triangles or InputTrianglesAdjacency execution modes."));
  150. }
  151. TEST_F(ValidateMode, FragmentNoOrigin) {
  152. const std::string spirv = R"(
  153. OpCapability Shader
  154. OpMemoryModel Logical GLSL450
  155. OpEntryPoint Fragment %main "main"
  156. )" + kVoidFunction;
  157. CompileSuccessfully(spirv);
  158. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  159. EXPECT_THAT(
  160. getDiagnosticString(),
  161. HasSubstr("Fragment execution model entry points require either an "
  162. "OriginUpperLeft or OriginLowerLeft execution mode."));
  163. }
  164. TEST_F(ValidateMode, FragmentBothOrigins) {
  165. const std::string spirv = R"(
  166. OpCapability Shader
  167. OpMemoryModel Logical GLSL450
  168. OpEntryPoint Fragment %main "main"
  169. OpExecutionMode %main OriginUpperLeft
  170. OpExecutionMode %main OriginLowerLeft
  171. )" + kVoidFunction;
  172. CompileSuccessfully(spirv);
  173. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  174. EXPECT_THAT(
  175. getDiagnosticString(),
  176. HasSubstr("Fragment execution model entry points can only specify one of "
  177. "OriginUpperLeft or OriginLowerLeft execution modes."));
  178. }
  179. TEST_F(ValidateMode, FragmentDepthGreaterAndLess) {
  180. const std::string spirv = R"(
  181. OpCapability Shader
  182. OpMemoryModel Logical GLSL450
  183. OpEntryPoint Fragment %main "main"
  184. OpExecutionMode %main OriginUpperLeft
  185. OpExecutionMode %main DepthGreater
  186. OpExecutionMode %main DepthLess
  187. )" + kVoidFunction;
  188. CompileSuccessfully(spirv);
  189. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  190. EXPECT_THAT(getDiagnosticString(),
  191. HasSubstr("Fragment execution model entry points can specify at "
  192. "most one of DepthGreater, DepthLess or DepthUnchanged "
  193. "execution modes."));
  194. }
  195. TEST_F(ValidateMode, FragmentDepthGreaterAndUnchanged) {
  196. const std::string spirv = R"(
  197. OpCapability Shader
  198. OpMemoryModel Logical GLSL450
  199. OpEntryPoint Fragment %main "main"
  200. OpExecutionMode %main OriginUpperLeft
  201. OpExecutionMode %main DepthGreater
  202. OpExecutionMode %main DepthUnchanged
  203. )" + kVoidFunction;
  204. CompileSuccessfully(spirv);
  205. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  206. EXPECT_THAT(getDiagnosticString(),
  207. HasSubstr("Fragment execution model entry points can specify at "
  208. "most one of DepthGreater, DepthLess or DepthUnchanged "
  209. "execution modes."));
  210. }
  211. TEST_F(ValidateMode, FragmentDepthLessAndUnchanged) {
  212. const std::string spirv = R"(
  213. OpCapability Shader
  214. OpMemoryModel Logical GLSL450
  215. OpEntryPoint Fragment %main "main"
  216. OpExecutionMode %main OriginUpperLeft
  217. OpExecutionMode %main DepthLess
  218. OpExecutionMode %main DepthUnchanged
  219. )" + kVoidFunction;
  220. CompileSuccessfully(spirv);
  221. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  222. EXPECT_THAT(getDiagnosticString(),
  223. HasSubstr("Fragment execution model entry points can specify at "
  224. "most one of DepthGreater, DepthLess or DepthUnchanged "
  225. "execution modes."));
  226. }
  227. TEST_F(ValidateMode, FragmentAllDepths) {
  228. const std::string spirv = R"(
  229. OpCapability Shader
  230. OpMemoryModel Logical GLSL450
  231. OpEntryPoint Fragment %main "main"
  232. OpExecutionMode %main OriginUpperLeft
  233. OpExecutionMode %main DepthGreater
  234. OpExecutionMode %main DepthLess
  235. OpExecutionMode %main DepthUnchanged
  236. )" + kVoidFunction;
  237. CompileSuccessfully(spirv);
  238. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  239. EXPECT_THAT(getDiagnosticString(),
  240. HasSubstr("Fragment execution model entry points can specify at "
  241. "most one of DepthGreater, DepthLess or DepthUnchanged "
  242. "execution modes."));
  243. }
  244. TEST_F(ValidateMode, TessellationControlSpacingEqualAndFractionalOdd) {
  245. const std::string spirv = R"(
  246. OpCapability Tessellation
  247. OpMemoryModel Logical GLSL450
  248. OpEntryPoint TessellationControl %main "main"
  249. OpExecutionMode %main SpacingEqual
  250. OpExecutionMode %main SpacingFractionalOdd
  251. )" + kVoidFunction;
  252. CompileSuccessfully(spirv);
  253. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  254. EXPECT_THAT(getDiagnosticString(),
  255. HasSubstr("Tessellation execution model entry points can specify "
  256. "at most one of SpacingEqual, SpacingFractionalOdd or "
  257. "SpacingFractionalEven execution modes."));
  258. }
  259. TEST_F(ValidateMode, TessellationControlSpacingEqualAndSpacingFractionalEven) {
  260. const std::string spirv = R"(
  261. OpCapability Tessellation
  262. OpMemoryModel Logical GLSL450
  263. OpEntryPoint TessellationControl %main "main"
  264. OpExecutionMode %main SpacingEqual
  265. OpExecutionMode %main SpacingFractionalEven
  266. )" + kVoidFunction;
  267. CompileSuccessfully(spirv);
  268. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  269. EXPECT_THAT(getDiagnosticString(),
  270. HasSubstr("Tessellation execution model entry points can specify "
  271. "at most one of SpacingEqual, SpacingFractionalOdd or "
  272. "SpacingFractionalEven execution modes."));
  273. }
  274. TEST_F(ValidateMode,
  275. TessellationControlSpacingFractionalOddAndSpacingFractionalEven) {
  276. const std::string spirv = R"(
  277. OpCapability Tessellation
  278. OpMemoryModel Logical GLSL450
  279. OpEntryPoint TessellationControl %main "main"
  280. OpExecutionMode %main SpacingFractionalOdd
  281. OpExecutionMode %main SpacingFractionalEven
  282. )" + kVoidFunction;
  283. CompileSuccessfully(spirv);
  284. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  285. EXPECT_THAT(getDiagnosticString(),
  286. HasSubstr("Tessellation execution model entry points can specify "
  287. "at most one of SpacingEqual, SpacingFractionalOdd or "
  288. "SpacingFractionalEven execution modes."));
  289. }
  290. TEST_F(ValidateMode, TessellationControlAllSpacing) {
  291. const std::string spirv = R"(
  292. OpCapability Tessellation
  293. OpMemoryModel Logical GLSL450
  294. OpEntryPoint TessellationControl %main "main"
  295. OpExecutionMode %main SpacingEqual
  296. OpExecutionMode %main SpacingFractionalOdd
  297. OpExecutionMode %main SpacingFractionalEven
  298. )" + kVoidFunction;
  299. CompileSuccessfully(spirv);
  300. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  301. EXPECT_THAT(getDiagnosticString(),
  302. HasSubstr("Tessellation execution model entry points can specify "
  303. "at most one of SpacingEqual, SpacingFractionalOdd or "
  304. "SpacingFractionalEven execution modes."));
  305. }
  306. TEST_F(ValidateMode,
  307. TessellationEvaluationSpacingEqualAndSpacingFractionalOdd) {
  308. const std::string spirv = R"(
  309. OpCapability Tessellation
  310. OpMemoryModel Logical GLSL450
  311. OpEntryPoint TessellationEvaluation %main "main"
  312. OpExecutionMode %main SpacingEqual
  313. OpExecutionMode %main SpacingFractionalOdd
  314. )" + kVoidFunction;
  315. CompileSuccessfully(spirv);
  316. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  317. EXPECT_THAT(getDiagnosticString(),
  318. HasSubstr("Tessellation execution model entry points can specify "
  319. "at most one of SpacingEqual, SpacingFractionalOdd or "
  320. "SpacingFractionalEven execution modes."));
  321. }
  322. TEST_F(ValidateMode,
  323. TessellationEvaluationSpacingEqualAndSpacingFractionalEven) {
  324. const std::string spirv = R"(
  325. OpCapability Tessellation
  326. OpMemoryModel Logical GLSL450
  327. OpEntryPoint TessellationEvaluation %main "main"
  328. OpExecutionMode %main SpacingEqual
  329. OpExecutionMode %main SpacingFractionalEven
  330. )" + kVoidFunction;
  331. CompileSuccessfully(spirv);
  332. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  333. EXPECT_THAT(getDiagnosticString(),
  334. HasSubstr("Tessellation execution model entry points can specify "
  335. "at most one of SpacingEqual, SpacingFractionalOdd or "
  336. "SpacingFractionalEven execution modes."));
  337. }
  338. TEST_F(ValidateMode,
  339. TessellationEvaluationSpacingFractionalOddAndSpacingFractionalEven) {
  340. const std::string spirv = R"(
  341. OpCapability Tessellation
  342. OpMemoryModel Logical GLSL450
  343. OpEntryPoint TessellationEvaluation %main "main"
  344. OpExecutionMode %main SpacingFractionalOdd
  345. OpExecutionMode %main SpacingFractionalEven
  346. )" + kVoidFunction;
  347. CompileSuccessfully(spirv);
  348. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  349. EXPECT_THAT(getDiagnosticString(),
  350. HasSubstr("Tessellation execution model entry points can specify "
  351. "at most one of SpacingEqual, SpacingFractionalOdd or "
  352. "SpacingFractionalEven execution modes."));
  353. }
  354. TEST_F(ValidateMode, TessellationEvaluationAllSpacing) {
  355. const std::string spirv = R"(
  356. OpCapability Tessellation
  357. OpMemoryModel Logical GLSL450
  358. OpEntryPoint TessellationEvaluation %main "main"
  359. OpExecutionMode %main SpacingEqual
  360. OpExecutionMode %main SpacingFractionalOdd
  361. OpExecutionMode %main SpacingFractionalEven
  362. )" + kVoidFunction;
  363. CompileSuccessfully(spirv);
  364. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  365. EXPECT_THAT(getDiagnosticString(),
  366. HasSubstr("Tessellation execution model entry points can specify "
  367. "at most one of SpacingEqual, SpacingFractionalOdd or "
  368. "SpacingFractionalEven execution modes."));
  369. }
  370. TEST_F(ValidateMode, TessellationControlBothVertex) {
  371. const std::string spirv = R"(
  372. OpCapability Tessellation
  373. OpMemoryModel Logical GLSL450
  374. OpEntryPoint TessellationControl %main "main"
  375. OpExecutionMode %main VertexOrderCw
  376. OpExecutionMode %main VertexOrderCcw
  377. )" + kVoidFunction;
  378. CompileSuccessfully(spirv);
  379. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  380. EXPECT_THAT(
  381. getDiagnosticString(),
  382. HasSubstr("Tessellation execution model entry points can specify at most "
  383. "one of VertexOrderCw or VertexOrderCcw execution modes."));
  384. }
  385. TEST_F(ValidateMode, TessellationEvaluationBothVertex) {
  386. const std::string spirv = R"(
  387. OpCapability Tessellation
  388. OpMemoryModel Logical GLSL450
  389. OpEntryPoint TessellationEvaluation %main "main"
  390. OpExecutionMode %main VertexOrderCw
  391. OpExecutionMode %main VertexOrderCcw
  392. )" + kVoidFunction;
  393. CompileSuccessfully(spirv);
  394. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  395. EXPECT_THAT(
  396. getDiagnosticString(),
  397. HasSubstr("Tessellation execution model entry points can specify at most "
  398. "one of VertexOrderCw or VertexOrderCcw execution modes."));
  399. }
  400. using ValidateModeGeometry = spvtest::ValidateBase<std::tuple<
  401. std::tuple<std::string, std::string, std::string, std::string, std::string>,
  402. std::tuple<std::string, std::string, std::string>>>;
  403. TEST_P(ValidateModeGeometry, ExecutionMode) {
  404. std::vector<std::string> input_modes;
  405. std::vector<std::string> output_modes;
  406. input_modes.push_back(std::get<0>(std::get<0>(GetParam())));
  407. input_modes.push_back(std::get<1>(std::get<0>(GetParam())));
  408. input_modes.push_back(std::get<2>(std::get<0>(GetParam())));
  409. input_modes.push_back(std::get<3>(std::get<0>(GetParam())));
  410. input_modes.push_back(std::get<4>(std::get<0>(GetParam())));
  411. output_modes.push_back(std::get<0>(std::get<1>(GetParam())));
  412. output_modes.push_back(std::get<1>(std::get<1>(GetParam())));
  413. output_modes.push_back(std::get<2>(std::get<1>(GetParam())));
  414. std::ostringstream sstr;
  415. sstr << "OpCapability Geometry\n";
  416. sstr << "OpMemoryModel Logical GLSL450\n";
  417. sstr << "OpEntryPoint Geometry %main \"main\"\n";
  418. size_t num_input_modes = 0;
  419. for (auto input : input_modes) {
  420. if (!input.empty()) {
  421. num_input_modes++;
  422. sstr << "OpExecutionMode %main " << input << "\n";
  423. }
  424. }
  425. size_t num_output_modes = 0;
  426. for (auto output : output_modes) {
  427. if (!output.empty()) {
  428. num_output_modes++;
  429. sstr << "OpExecutionMode %main " << output << "\n";
  430. }
  431. }
  432. sstr << "%void = OpTypeVoid\n";
  433. sstr << "%void_fn = OpTypeFunction %void\n";
  434. sstr << "%int = OpTypeInt 32 0\n";
  435. sstr << "%int1 = OpConstant %int 1\n";
  436. sstr << "%main = OpFunction %void None %void_fn\n";
  437. sstr << "%entry = OpLabel\n";
  438. sstr << "OpReturn\n";
  439. sstr << "OpFunctionEnd\n";
  440. CompileSuccessfully(sstr.str());
  441. if (num_input_modes == 1 && num_output_modes == 1) {
  442. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  443. } else {
  444. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  445. if (num_input_modes != 1) {
  446. EXPECT_THAT(getDiagnosticString(),
  447. HasSubstr("Geometry execution model entry points must "
  448. "specify exactly one of InputPoints, InputLines, "
  449. "InputLinesAdjacency, Triangles or "
  450. "InputTrianglesAdjacency execution modes."));
  451. } else {
  452. EXPECT_THAT(
  453. getDiagnosticString(),
  454. HasSubstr("Geometry execution model entry points must specify "
  455. "exactly one of OutputPoints, OutputLineStrip or "
  456. "OutputTriangleStrip execution modes."));
  457. }
  458. }
  459. }
  460. INSTANTIATE_TEST_SUITE_P(
  461. GeometryRequiredModes, ValidateModeGeometry,
  462. Combine(Combine(Values("InputPoints", ""), Values("InputLines", ""),
  463. Values("InputLinesAdjacency", ""), Values("Triangles", ""),
  464. Values("InputTrianglesAdjacency", "")),
  465. Combine(Values("OutputPoints", ""), Values("OutputLineStrip", ""),
  466. Values("OutputTriangleStrip", ""))));
  467. using ValidateModeExecution =
  468. spvtest::ValidateBase<std::tuple<spv_result_t, std::string, std::string,
  469. std::string, spv_target_env>>;
  470. TEST_P(ValidateModeExecution, ExecutionMode) {
  471. const spv_result_t expectation = std::get<0>(GetParam());
  472. const std::string error = std::get<1>(GetParam());
  473. const std::string model = std::get<2>(GetParam());
  474. const std::string mode = std::get<3>(GetParam());
  475. const spv_target_env env = std::get<4>(GetParam());
  476. std::ostringstream sstr;
  477. sstr << "OpCapability Shader\n";
  478. sstr << "OpCapability Geometry\n";
  479. sstr << "OpCapability Tessellation\n";
  480. sstr << "OpCapability TransformFeedback\n";
  481. if (!spvIsVulkanEnv(env)) {
  482. sstr << "OpCapability Kernel\n";
  483. if (env == SPV_ENV_UNIVERSAL_1_3) {
  484. sstr << "OpCapability SubgroupDispatch\n";
  485. }
  486. }
  487. sstr << "OpMemoryModel Logical GLSL450\n";
  488. sstr << "OpEntryPoint " << model << " %main \"main\"\n";
  489. if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
  490. mode.find("SubgroupsPerWorkgroupId") == 0) {
  491. sstr << "OpExecutionModeId %main " << mode << "\n";
  492. } else {
  493. sstr << "OpExecutionMode %main " << mode << "\n";
  494. }
  495. if (model == "Geometry") {
  496. if (!(mode.find("InputPoints") == 0 || mode.find("InputLines") == 0 ||
  497. mode.find("InputLinesAdjacency") == 0 ||
  498. mode.find("Triangles") == 0 ||
  499. mode.find("InputTrianglesAdjacency") == 0)) {
  500. // Exactly one of the above modes is required for Geometry shaders.
  501. sstr << "OpExecutionMode %main InputPoints\n";
  502. }
  503. if (!(mode.find("OutputPoints") == 0 || mode.find("OutputLineStrip") == 0 ||
  504. mode.find("OutputTriangleStrip") == 0)) {
  505. // Exactly one of the above modes is required for Geometry shaders.
  506. sstr << "OpExecutionMode %main OutputPoints\n";
  507. }
  508. } else if (model == "Fragment") {
  509. if (!(mode.find("OriginUpperLeft") == 0 ||
  510. mode.find("OriginLowerLeft") == 0)) {
  511. // Exactly one of the above modes is required for Fragment shaders.
  512. sstr << "OpExecutionMode %main OriginUpperLeft\n";
  513. }
  514. }
  515. sstr << "%void = OpTypeVoid\n";
  516. sstr << "%void_fn = OpTypeFunction %void\n";
  517. sstr << "%int = OpTypeInt 32 0\n";
  518. sstr << "%int1 = OpConstant %int 1\n";
  519. sstr << "%main = OpFunction %void None %void_fn\n";
  520. sstr << "%entry = OpLabel\n";
  521. sstr << "OpReturn\n";
  522. sstr << "OpFunctionEnd\n";
  523. CompileSuccessfully(sstr.str(), env);
  524. EXPECT_THAT(expectation, ValidateInstructions(env));
  525. if (expectation != SPV_SUCCESS) {
  526. EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
  527. }
  528. }
  529. INSTANTIATE_TEST_SUITE_P(
  530. ValidateModeGeometryOnlyGoodSpv10, ValidateModeExecution,
  531. Combine(Values(SPV_SUCCESS), Values(""), Values("Geometry"),
  532. Values("Invocations 3", "InputPoints", "InputLines",
  533. "InputLinesAdjacency", "InputTrianglesAdjacency",
  534. "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
  535. Values(SPV_ENV_UNIVERSAL_1_0)));
  536. INSTANTIATE_TEST_SUITE_P(
  537. ValidateModeGeometryOnlyBadSpv10, ValidateModeExecution,
  538. Combine(Values(SPV_ERROR_INVALID_DATA),
  539. Values("Execution mode can only be used with the Geometry "
  540. "execution model."),
  541. Values("Fragment", "TessellationEvaluation", "TessellationControl",
  542. "GLCompute", "Vertex", "Kernel"),
  543. Values("Invocations 3", "InputPoints", "InputLines",
  544. "InputLinesAdjacency", "InputTrianglesAdjacency",
  545. "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
  546. Values(SPV_ENV_UNIVERSAL_1_0)));
  547. INSTANTIATE_TEST_SUITE_P(
  548. ValidateModeTessellationOnlyGoodSpv10, ValidateModeExecution,
  549. Combine(Values(SPV_SUCCESS), Values(""),
  550. Values("TessellationControl", "TessellationEvaluation"),
  551. Values("SpacingEqual", "SpacingFractionalEven",
  552. "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
  553. "PointMode", "Quads", "Isolines"),
  554. Values(SPV_ENV_UNIVERSAL_1_0)));
  555. INSTANTIATE_TEST_SUITE_P(
  556. ValidateModeTessellationOnlyBadSpv10, ValidateModeExecution,
  557. Combine(Values(SPV_ERROR_INVALID_DATA),
  558. Values("Execution mode can only be used with a tessellation "
  559. "execution model."),
  560. Values("Fragment", "Geometry", "GLCompute", "Vertex", "Kernel"),
  561. Values("SpacingEqual", "SpacingFractionalEven",
  562. "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
  563. "PointMode", "Quads", "Isolines"),
  564. Values(SPV_ENV_UNIVERSAL_1_0)));
  565. INSTANTIATE_TEST_SUITE_P(ValidateModeGeometryAndTessellationGoodSpv10,
  566. ValidateModeExecution,
  567. Combine(Values(SPV_SUCCESS), Values(""),
  568. Values("TessellationControl",
  569. "TessellationEvaluation", "Geometry"),
  570. Values("Triangles", "OutputVertices 3"),
  571. Values(SPV_ENV_UNIVERSAL_1_0)));
  572. INSTANTIATE_TEST_SUITE_P(
  573. ValidateModeGeometryAndTessellationBadSpv10, ValidateModeExecution,
  574. Combine(Values(SPV_ERROR_INVALID_DATA),
  575. Values("Execution mode can only be used with a Geometry or "
  576. "tessellation execution model."),
  577. Values("Fragment", "GLCompute", "Vertex", "Kernel"),
  578. Values("Triangles", "OutputVertices 3"),
  579. Values(SPV_ENV_UNIVERSAL_1_0)));
  580. INSTANTIATE_TEST_SUITE_P(
  581. ValidateModeFragmentOnlyGoodSpv10, ValidateModeExecution,
  582. Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
  583. Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
  584. "EarlyFragmentTests", "DepthReplacing", "DepthLess",
  585. "DepthUnchanged"),
  586. Values(SPV_ENV_UNIVERSAL_1_0)));
  587. INSTANTIATE_TEST_SUITE_P(
  588. ValidateModeFragmentOnlyBadSpv10, ValidateModeExecution,
  589. Combine(Values(SPV_ERROR_INVALID_DATA),
  590. Values("Execution mode can only be used with the Fragment "
  591. "execution model."),
  592. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  593. "GLCompute", "Vertex", "Kernel"),
  594. Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
  595. "EarlyFragmentTests", "DepthReplacing", "DepthGreater",
  596. "DepthLess", "DepthUnchanged"),
  597. Values(SPV_ENV_UNIVERSAL_1_0)));
  598. INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution,
  599. Combine(Values(SPV_SUCCESS), Values(""),
  600. Values("Kernel"),
  601. Values("LocalSizeHint 1 1 1", "VecTypeHint 4",
  602. "ContractionOff",
  603. "LocalSizeHintId %int1"),
  604. Values(SPV_ENV_UNIVERSAL_1_3)));
  605. INSTANTIATE_TEST_SUITE_P(
  606. ValidateModeKernelOnlyBadSpv13, ValidateModeExecution,
  607. Combine(
  608. Values(SPV_ERROR_INVALID_DATA),
  609. Values(
  610. "Execution mode can only be used with the Kernel execution model."),
  611. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  612. "GLCompute", "Vertex", "Fragment"),
  613. Values("LocalSizeHint 1 1 1", "VecTypeHint 4", "ContractionOff",
  614. "LocalSizeHintId %int1"),
  615. Values(SPV_ENV_UNIVERSAL_1_3)));
  616. INSTANTIATE_TEST_SUITE_P(
  617. ValidateModeGLComputeAndKernelGoodSpv13, ValidateModeExecution,
  618. Combine(Values(SPV_SUCCESS), Values(""), Values("Kernel", "GLCompute"),
  619. Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
  620. Values(SPV_ENV_UNIVERSAL_1_3)));
  621. INSTANTIATE_TEST_SUITE_P(
  622. ValidateModeGLComputeAndKernelBadSpv13, ValidateModeExecution,
  623. Combine(Values(SPV_ERROR_INVALID_DATA),
  624. Values("Execution mode can only be used with a Kernel or GLCompute "
  625. "execution model."),
  626. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  627. "Fragment", "Vertex"),
  628. Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
  629. Values(SPV_ENV_UNIVERSAL_1_3)));
  630. INSTANTIATE_TEST_SUITE_P(
  631. ValidateModeAllGoodSpv13, ValidateModeExecution,
  632. Combine(Values(SPV_SUCCESS), Values(""),
  633. Values("Kernel", "GLCompute", "Geometry", "TessellationControl",
  634. "TessellationEvaluation", "Fragment", "Vertex"),
  635. Values("Xfb", "Initializer", "Finalizer", "SubgroupSize 1",
  636. "SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
  637. Values(SPV_ENV_UNIVERSAL_1_3)));
  638. TEST_F(ValidateModeExecution, MeshNVLocalSize) {
  639. const std::string spirv = R"(
  640. OpCapability Shader
  641. OpCapability MeshShadingNV
  642. OpExtension "SPV_NV_mesh_shader"
  643. OpMemoryModel Logical GLSL450
  644. OpEntryPoint MeshNV %main "main"
  645. OpExecutionMode %main LocalSize 1 1 1
  646. )" + kVoidFunction;
  647. CompileSuccessfully(spirv);
  648. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  649. }
  650. TEST_F(ValidateModeExecution, TaskNVLocalSize) {
  651. const std::string spirv = R"(
  652. OpCapability Shader
  653. OpCapability MeshShadingNV
  654. OpExtension "SPV_NV_mesh_shader"
  655. OpMemoryModel Logical GLSL450
  656. OpEntryPoint TaskNV %main "main"
  657. OpExecutionMode %main LocalSize 1 1 1
  658. )" + kVoidFunction;
  659. CompileSuccessfully(spirv);
  660. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  661. }
  662. TEST_F(ValidateModeExecution, MeshNVOutputPoints) {
  663. const std::string spirv = R"(
  664. OpCapability Shader
  665. OpCapability MeshShadingNV
  666. OpExtension "SPV_NV_mesh_shader"
  667. OpMemoryModel Logical GLSL450
  668. OpEntryPoint MeshNV %main "main"
  669. OpExecutionMode %main OutputPoints
  670. )" + kVoidFunction;
  671. CompileSuccessfully(spirv);
  672. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  673. }
  674. TEST_F(ValidateModeExecution, MeshNVOutputVertices) {
  675. const std::string spirv = R"(
  676. OpCapability Shader
  677. OpCapability MeshShadingNV
  678. OpExtension "SPV_NV_mesh_shader"
  679. OpMemoryModel Logical GLSL450
  680. OpEntryPoint MeshNV %main "main"
  681. OpExecutionMode %main OutputVertices 42
  682. )" + kVoidFunction;
  683. CompileSuccessfully(spirv);
  684. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  685. }
  686. TEST_F(ValidateModeExecution, MeshNVLocalSizeId) {
  687. const std::string spirv = R"(
  688. OpCapability Shader
  689. OpCapability MeshShadingNV
  690. OpExtension "SPV_NV_mesh_shader"
  691. OpMemoryModel Logical GLSL450
  692. OpEntryPoint MeshNV %main "main"
  693. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  694. %int = OpTypeInt 32 0
  695. %int_1 = OpConstant %int 1
  696. )" + kVoidFunction;
  697. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  698. CompileSuccessfully(spirv, env);
  699. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  700. }
  701. TEST_F(ValidateModeExecution, TaskNVLocalSizeId) {
  702. const std::string spirv = R"(
  703. OpCapability Shader
  704. OpCapability MeshShadingNV
  705. OpExtension "SPV_NV_mesh_shader"
  706. OpMemoryModel Logical GLSL450
  707. OpEntryPoint TaskNV %main "main"
  708. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  709. %int = OpTypeInt 32 0
  710. %int_1 = OpConstant %int 1
  711. )" + kVoidFunction;
  712. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  713. CompileSuccessfully(spirv, env);
  714. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  715. }
  716. TEST_F(ValidateModeExecution, ExecModeSubgroupsPerWorkgroupIdBad) {
  717. const std::string spirv = R"(
  718. OpCapability Shader
  719. OpCapability SubgroupDispatch
  720. OpMemoryModel Logical GLSL450
  721. OpEntryPoint Vertex %main "main"
  722. OpExecutionMode %main SubgroupsPerWorkgroupId %int_1
  723. %int = OpTypeInt 32 0
  724. %int_1 = OpConstant %int 1
  725. )" + kVoidFunction;
  726. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  727. CompileSuccessfully(spirv, env);
  728. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  729. EXPECT_THAT(getDiagnosticString(),
  730. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  731. "is an execution mode that takes no Extra Operands"));
  732. }
  733. TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdGood) {
  734. const std::string spirv = R"(
  735. OpCapability Shader
  736. OpCapability SubgroupDispatch
  737. OpMemoryModel Logical GLSL450
  738. OpEntryPoint Vertex %main "main"
  739. OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1
  740. %int = OpTypeInt 32 0
  741. %int_1 = OpConstant %int 1
  742. )" + kVoidFunction;
  743. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  744. CompileSuccessfully(spirv, env);
  745. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  746. }
  747. TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdNonConstantBad) {
  748. const std::string spirv = R"(
  749. OpCapability Shader
  750. OpCapability SubgroupDispatch
  751. OpMemoryModel Logical GLSL450
  752. OpEntryPoint Vertex %main "main"
  753. OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1
  754. %int = OpTypeInt 32 0
  755. %int_ptr = OpTypePointer Private %int
  756. %int_1 = OpVariable %int_ptr Private
  757. )" + kVoidFunction;
  758. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  759. CompileSuccessfully(spirv, env);
  760. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
  761. EXPECT_THAT(getDiagnosticString(),
  762. HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
  763. "constant instructions."));
  764. }
  765. TEST_F(ValidateModeExecution, ExecModeLocalSizeHintIdBad) {
  766. const std::string spirv = R"(
  767. OpCapability Kernel
  768. OpCapability Shader
  769. OpMemoryModel Logical GLSL450
  770. OpEntryPoint Kernel %main "main"
  771. OpExecutionMode %main LocalSizeHintId %int_1
  772. %int = OpTypeInt 32 0
  773. %int_1 = OpConstant %int 1
  774. )" + kVoidFunction;
  775. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  776. CompileSuccessfully(spirv, env);
  777. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  778. EXPECT_THAT(getDiagnosticString(),
  779. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  780. "is an execution mode that takes no Extra Operands"));
  781. }
  782. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdGood) {
  783. const std::string spirv = R"(
  784. OpCapability Kernel
  785. OpCapability Shader
  786. OpMemoryModel Logical GLSL450
  787. OpEntryPoint Kernel %main "main"
  788. OpExecutionModeId %main LocalSizeHintId %int_1
  789. %int = OpTypeInt 32 0
  790. %int_1 = OpConstant %int 1
  791. )" + kVoidFunction;
  792. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  793. CompileSuccessfully(spirv, env);
  794. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  795. }
  796. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdNonConstantBad) {
  797. const std::string spirv = R"(
  798. OpCapability Kernel
  799. OpCapability Shader
  800. OpMemoryModel Logical GLSL450
  801. OpEntryPoint Vertex %main "main"
  802. OpExecutionModeId %main LocalSizeHintId %int_1
  803. %int = OpTypeInt 32 0
  804. %int_ptr = OpTypePointer Private %int
  805. %int_1 = OpVariable %int_ptr Private
  806. )" + kVoidFunction;
  807. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  808. CompileSuccessfully(spirv, env);
  809. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
  810. EXPECT_THAT(getDiagnosticString(),
  811. HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
  812. "constant instructions."));
  813. }
  814. TEST_F(ValidateModeExecution, ExecModeLocalSizeIdBad) {
  815. const std::string spirv = R"(
  816. OpCapability Kernel
  817. OpCapability Shader
  818. OpMemoryModel Logical GLSL450
  819. OpEntryPoint Kernel %main "main"
  820. OpExecutionMode %main LocalSizeId %int_1 %int_1 %int_1
  821. %int = OpTypeInt 32 0
  822. %int_1 = OpConstant %int 1
  823. )" + kVoidFunction;
  824. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  825. CompileSuccessfully(spirv, env);
  826. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  827. EXPECT_THAT(getDiagnosticString(),
  828. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  829. "is an execution mode that takes no Extra Operands"));
  830. }
  831. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdGood) {
  832. const std::string spirv = R"(
  833. OpCapability Kernel
  834. OpCapability Shader
  835. OpMemoryModel Logical GLSL450
  836. OpEntryPoint Kernel %main "main"
  837. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  838. %int = OpTypeInt 32 0
  839. %int_1 = OpConstant %int 1
  840. )" + kVoidFunction;
  841. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  842. CompileSuccessfully(spirv, env);
  843. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  844. }
  845. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdNonConstantBad) {
  846. const std::string spirv = R"(
  847. OpCapability Kernel
  848. OpCapability Shader
  849. OpMemoryModel Logical GLSL450
  850. OpEntryPoint Vertex %main "main"
  851. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  852. %int = OpTypeInt 32 0
  853. %int_ptr = OpTypePointer Private %int
  854. %int_1 = OpVariable %int_ptr Private
  855. )" + kVoidFunction;
  856. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  857. CompileSuccessfully(spirv, env);
  858. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
  859. EXPECT_THAT(getDiagnosticString(),
  860. HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
  861. "constant instructions."));
  862. }
  863. TEST_F(ValidateMode, FragmentShaderInterlockVertexBad) {
  864. const std::string spirv = R"(
  865. OpCapability Shader
  866. OpCapability FragmentShaderPixelInterlockEXT
  867. OpExtension "SPV_EXT_fragment_shader_interlock"
  868. OpMemoryModel Logical GLSL450
  869. OpEntryPoint Vertex %main "main"
  870. OpExecutionMode %main PixelInterlockOrderedEXT
  871. )" + kVoidFunction;
  872. CompileSuccessfully(spirv);
  873. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  874. EXPECT_THAT(
  875. getDiagnosticString(),
  876. HasSubstr(
  877. "Execution mode can only be used with the Fragment execution model"));
  878. }
  879. TEST_F(ValidateMode, FragmentShaderInterlockTooManyModesBad) {
  880. const std::string spirv = R"(
  881. OpCapability Shader
  882. OpCapability FragmentShaderPixelInterlockEXT
  883. OpCapability FragmentShaderSampleInterlockEXT
  884. OpExtension "SPV_EXT_fragment_shader_interlock"
  885. OpMemoryModel Logical GLSL450
  886. OpEntryPoint Fragment %main "main"
  887. OpExecutionMode %main OriginUpperLeft
  888. OpExecutionMode %main PixelInterlockOrderedEXT
  889. OpExecutionMode %main SampleInterlockOrderedEXT
  890. )" + kVoidFunction;
  891. CompileSuccessfully(spirv);
  892. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  893. EXPECT_THAT(
  894. getDiagnosticString(),
  895. HasSubstr("Fragment execution model entry points can specify at most "
  896. "one fragment shader interlock execution mode"));
  897. }
  898. TEST_F(ValidateMode, FragmentShaderInterlockNoModeBad) {
  899. const std::string spirv = R"(
  900. OpCapability Shader
  901. OpCapability FragmentShaderPixelInterlockEXT
  902. OpExtension "SPV_EXT_fragment_shader_interlock"
  903. OpMemoryModel Logical GLSL450
  904. OpEntryPoint Fragment %main "main"
  905. OpExecutionMode %main OriginUpperLeft
  906. %void = OpTypeVoid
  907. %void_fn = OpTypeFunction %void
  908. %func = OpFunction %void None %void_fn
  909. %entryf = OpLabel
  910. OpBeginInvocationInterlockEXT
  911. OpEndInvocationInterlockEXT
  912. OpReturn
  913. OpFunctionEnd
  914. %main = OpFunction %void None %void_fn
  915. %entry = OpLabel
  916. %1 = OpFunctionCall %void %func
  917. OpReturn
  918. OpFunctionEnd
  919. )";
  920. CompileSuccessfully(spirv);
  921. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
  922. EXPECT_THAT(
  923. getDiagnosticString(),
  924. HasSubstr(
  925. "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT require a "
  926. "fragment shader interlock execution mode"));
  927. }
  928. TEST_F(ValidateMode, FragmentShaderInterlockGood) {
  929. const std::string spirv = R"(
  930. OpCapability Shader
  931. OpCapability FragmentShaderPixelInterlockEXT
  932. OpExtension "SPV_EXT_fragment_shader_interlock"
  933. OpMemoryModel Logical GLSL450
  934. OpEntryPoint Fragment %main "main"
  935. OpExecutionMode %main OriginUpperLeft
  936. OpExecutionMode %main PixelInterlockOrderedEXT
  937. %void = OpTypeVoid
  938. %void_fn = OpTypeFunction %void
  939. %func = OpFunction %void None %void_fn
  940. %entryf = OpLabel
  941. OpBeginInvocationInterlockEXT
  942. OpEndInvocationInterlockEXT
  943. OpReturn
  944. OpFunctionEnd
  945. %main = OpFunction %void None %void_fn
  946. %entry = OpLabel
  947. %1 = OpFunctionCall %void %func
  948. OpReturn
  949. OpFunctionEnd
  950. )";
  951. CompileSuccessfully(spirv);
  952. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  953. }
  954. TEST_F(ValidateMode, FragmentShaderDemoteVertexBad) {
  955. const std::string spirv = R"(
  956. OpCapability Shader
  957. OpCapability DemoteToHelperInvocationEXT
  958. OpExtension "SPV_EXT_demote_to_helper_invocation"
  959. OpMemoryModel Logical GLSL450
  960. OpEntryPoint Vertex %main "main"
  961. %bool = OpTypeBool
  962. %void = OpTypeVoid
  963. %void_fn = OpTypeFunction %void
  964. %main = OpFunction %void None %void_fn
  965. %entry = OpLabel
  966. OpDemoteToHelperInvocationEXT
  967. %1 = OpIsHelperInvocationEXT %bool
  968. OpReturn
  969. OpFunctionEnd
  970. )";
  971. CompileSuccessfully(spirv);
  972. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
  973. EXPECT_THAT(
  974. getDiagnosticString(),
  975. HasSubstr(
  976. "OpDemoteToHelperInvocationEXT requires Fragment execution model"));
  977. EXPECT_THAT(
  978. getDiagnosticString(),
  979. HasSubstr("OpIsHelperInvocationEXT requires Fragment execution model"));
  980. }
  981. TEST_F(ValidateMode, FragmentShaderDemoteGood) {
  982. const std::string spirv = R"(
  983. OpCapability Shader
  984. OpCapability DemoteToHelperInvocationEXT
  985. OpExtension "SPV_EXT_demote_to_helper_invocation"
  986. OpMemoryModel Logical GLSL450
  987. OpEntryPoint Fragment %main "main"
  988. OpExecutionMode %main OriginUpperLeft
  989. %bool = OpTypeBool
  990. %void = OpTypeVoid
  991. %void_fn = OpTypeFunction %void
  992. %main = OpFunction %void None %void_fn
  993. %entry = OpLabel
  994. OpDemoteToHelperInvocationEXT
  995. %1 = OpIsHelperInvocationEXT %bool
  996. OpReturn
  997. OpFunctionEnd
  998. )";
  999. CompileSuccessfully(spirv);
  1000. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  1001. }
  1002. TEST_F(ValidateMode, FragmentShaderDemoteBadType) {
  1003. const std::string spirv = R"(
  1004. OpCapability Shader
  1005. OpCapability DemoteToHelperInvocationEXT
  1006. OpExtension "SPV_EXT_demote_to_helper_invocation"
  1007. OpMemoryModel Logical GLSL450
  1008. OpEntryPoint Fragment %main "main"
  1009. OpExecutionMode %main OriginUpperLeft
  1010. %u32 = OpTypeInt 32 0
  1011. %void = OpTypeVoid
  1012. %void_fn = OpTypeFunction %void
  1013. %main = OpFunction %void None %void_fn
  1014. %entry = OpLabel
  1015. OpDemoteToHelperInvocationEXT
  1016. %1 = OpIsHelperInvocationEXT %u32
  1017. OpReturn
  1018. OpFunctionEnd
  1019. )";
  1020. CompileSuccessfully(spirv);
  1021. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1022. EXPECT_THAT(getDiagnosticString(),
  1023. HasSubstr("Expected bool scalar type as Result Type"));
  1024. }
  1025. } // namespace
  1026. } // namespace val
  1027. } // namespace spvtools