val_modes_test.cpp 44 KB

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