val_modes_test.cpp 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741
  1. // Copyright (c) 2018 Google LLC.
  2. // Modifications Copyright (C) 2024 Advanced Micro Devices, Inc. All rights
  3. // reserved.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. #include <sstream>
  17. #include <string>
  18. #include <vector>
  19. #include "gmock/gmock.h"
  20. #include "source/spirv_target_env.h"
  21. #include "test/unit_spirv.h"
  22. #include "test/val/val_fixtures.h"
  23. namespace spvtools {
  24. namespace val {
  25. namespace {
  26. using ::testing::Combine;
  27. using ::testing::HasSubstr;
  28. using ::testing::Values;
  29. using ::testing::ValuesIn;
  30. using ValidateMode = spvtest::ValidateBase<bool>;
  31. const std::string kVoidFunction = R"(%void = OpTypeVoid
  32. %void_fn = OpTypeFunction %void
  33. %main = OpFunction %void None %void_fn
  34. %entry = OpLabel
  35. OpReturn
  36. OpFunctionEnd
  37. )";
  38. TEST_F(ValidateMode, GLComputeNoMode) {
  39. const std::string spirv = R"(
  40. OpCapability Shader
  41. OpMemoryModel Logical GLSL450
  42. OpEntryPoint GLCompute %main "main"
  43. )" + kVoidFunction;
  44. CompileSuccessfully(spirv);
  45. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  46. }
  47. TEST_F(ValidateMode, GLComputeNoModeVulkan) {
  48. const std::string spirv = R"(
  49. OpCapability Shader
  50. OpMemoryModel Logical GLSL450
  51. OpEntryPoint GLCompute %main "main"
  52. )" + kVoidFunction;
  53. spv_target_env env = SPV_ENV_VULKAN_1_0;
  54. CompileSuccessfully(spirv, env);
  55. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  56. EXPECT_THAT(getDiagnosticString(),
  57. AnyVUID("VUID-StandaloneSpirv-LocalSize-06426"));
  58. EXPECT_THAT(
  59. getDiagnosticString(),
  60. HasSubstr(
  61. "In the Vulkan environment, GLCompute execution model entry "
  62. "points require either the LocalSize or LocalSizeId execution mode "
  63. "or an object decorated with WorkgroupSize must be specified."));
  64. }
  65. TEST_F(ValidateMode, GLComputeNoModeVulkanWorkgroupSize) {
  66. const std::string spirv = R"(
  67. OpCapability Shader
  68. OpMemoryModel Logical GLSL450
  69. OpEntryPoint GLCompute %main "main"
  70. OpDecorate %int3_1 BuiltIn WorkgroupSize
  71. %int = OpTypeInt 32 0
  72. %int3 = OpTypeVector %int 3
  73. %int_1 = OpConstant %int 1
  74. %int3_1 = OpConstantComposite %int3 %int_1 %int_1 %int_1
  75. )" + kVoidFunction;
  76. spv_target_env env = SPV_ENV_VULKAN_1_0;
  77. CompileSuccessfully(spirv, env);
  78. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  79. }
  80. TEST_F(ValidateMode, GLComputeZeroWorkgroupSize) {
  81. const std::string spirv = R"(
  82. OpCapability Shader
  83. OpMemoryModel Logical GLSL450
  84. OpEntryPoint GLCompute %main "main"
  85. OpDecorate %int3_1 BuiltIn WorkgroupSize
  86. %int = OpTypeInt 32 0
  87. %int3 = OpTypeVector %int 3
  88. %int_0 = OpConstant %int 0
  89. %int_1 = OpConstant %int 1
  90. %int3_1 = OpConstantComposite %int3 %int_1 %int_0 %int_0
  91. )" + kVoidFunction;
  92. CompileSuccessfully(spirv);
  93. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  94. EXPECT_THAT(
  95. getDiagnosticString(),
  96. HasSubstr(
  97. "WorkgroupSize decorations must not have a static product of zero"));
  98. }
  99. TEST_F(ValidateMode, GLComputeZeroSpecWorkgroupSize) {
  100. const std::string spirv = R"(
  101. OpCapability Shader
  102. OpMemoryModel Logical GLSL450
  103. OpEntryPoint GLCompute %main "main"
  104. OpDecorate %int3_1 BuiltIn WorkgroupSize
  105. %int = OpTypeInt 32 0
  106. %int3 = OpTypeVector %int 3
  107. %int_0 = OpSpecConstant %int 0
  108. %int_1 = OpConstant %int 1
  109. %int3_1 = OpConstantComposite %int3 %int_1 %int_0 %int_0
  110. )" + kVoidFunction;
  111. CompileSuccessfully(spirv);
  112. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  113. }
  114. TEST_F(ValidateMode, GLComputeZeroSpecCompositeWorkgroupSize) {
  115. const std::string spirv = R"(
  116. OpCapability Shader
  117. OpMemoryModel Logical GLSL450
  118. OpEntryPoint GLCompute %main "main"
  119. OpDecorate %int3_1 BuiltIn WorkgroupSize
  120. %int = OpTypeInt 32 0
  121. %int3 = OpTypeVector %int 3
  122. %int_0 = OpSpecConstant %int 0
  123. %int_1 = OpSpecConstant %int 1
  124. %int3_1 = OpSpecConstantComposite %int3 %int_1 %int_0 %int_0
  125. )" + kVoidFunction;
  126. CompileSuccessfully(spirv);
  127. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  128. }
  129. TEST_F(ValidateMode, KernelZeroWorkgroupSizeConstant) {
  130. const std::string spirv = R"(
  131. OpCapability Addresses
  132. OpCapability Linkage
  133. OpCapability Kernel
  134. OpMemoryModel Physical32 OpenCL
  135. OpEntryPoint Kernel %main "main"
  136. OpDecorate %int3_1 BuiltIn WorkgroupSize
  137. %int = OpTypeInt 32 0
  138. %int3 = OpTypeVector %int 3
  139. %int_0 = OpConstant %int 0
  140. %int_1 = OpConstant %int 1
  141. %int3_1 = OpConstantComposite %int3 %int_1 %int_0 %int_0
  142. )" + kVoidFunction;
  143. CompileSuccessfully(spirv);
  144. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
  145. EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
  146. }
  147. TEST_F(ValidateMode, KernelZeroWorkgroupSizeVariable) {
  148. const std::string spirv = R"(
  149. OpCapability Addresses
  150. OpCapability Linkage
  151. OpCapability Kernel
  152. OpMemoryModel Physical32 OpenCL
  153. OpEntryPoint Kernel %main "main"
  154. OpDecorate %var BuiltIn WorkgroupSize
  155. %int = OpTypeInt 32 0
  156. %int3 = OpTypeVector %int 3
  157. %ptr = OpTypePointer Input %int3
  158. %var = OpVariable %ptr Input
  159. )" + kVoidFunction;
  160. CompileSuccessfully(spirv);
  161. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  162. }
  163. TEST_F(ValidateMode, GLComputeVulkanLocalSize) {
  164. const std::string spirv = R"(
  165. OpCapability Shader
  166. OpMemoryModel Logical GLSL450
  167. OpEntryPoint GLCompute %main "main"
  168. OpExecutionMode %main LocalSize 1 1 1
  169. )" + kVoidFunction;
  170. spv_target_env env = SPV_ENV_VULKAN_1_0;
  171. CompileSuccessfully(spirv, env);
  172. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  173. }
  174. TEST_F(ValidateMode, GLComputeZeroLocalSize) {
  175. const std::string spirv = R"(
  176. OpCapability Shader
  177. OpMemoryModel Logical GLSL450
  178. OpEntryPoint GLCompute %main "main"
  179. OpExecutionMode %main LocalSize 1 1 0
  180. )" + kVoidFunction;
  181. CompileSuccessfully(spirv);
  182. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  183. EXPECT_THAT(
  184. getDiagnosticString(),
  185. HasSubstr("Local Size execution mode must not have a product of zero"));
  186. }
  187. TEST_F(ValidateMode, KernelZeroLocalSize) {
  188. const std::string spirv = R"(
  189. OpCapability Addresses
  190. OpCapability Linkage
  191. OpCapability Kernel
  192. OpMemoryModel Physical32 OpenCL
  193. OpEntryPoint Kernel %main "main"
  194. OpExecutionMode %main LocalSize 1 1 0
  195. )" + kVoidFunction;
  196. CompileSuccessfully(spirv);
  197. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  198. EXPECT_THAT(
  199. getDiagnosticString(),
  200. HasSubstr("Local Size execution mode must not have a product of zero"));
  201. }
  202. TEST_F(ValidateMode, GLComputeVulkanLocalSizeIdBad) {
  203. const std::string spirv = R"(
  204. OpCapability Shader
  205. OpMemoryModel Logical GLSL450
  206. OpEntryPoint GLCompute %main "main"
  207. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  208. %int = OpTypeInt 32 0
  209. %int_1 = OpConstant %int 1
  210. )" + kVoidFunction;
  211. spv_target_env env = SPV_ENV_VULKAN_1_1; // need SPIR-V 1.2
  212. CompileSuccessfully(spirv, env);
  213. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  214. EXPECT_THAT(
  215. getDiagnosticString(),
  216. HasSubstr("LocalSizeId mode is not allowed by the current environment."));
  217. }
  218. TEST_F(ValidateMode, GLComputeVulkanLocalSizeIdGood) {
  219. const std::string spirv = R"(
  220. OpCapability Shader
  221. OpMemoryModel Logical GLSL450
  222. OpEntryPoint GLCompute %main "main"
  223. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  224. %int = OpTypeInt 32 0
  225. %int_1 = OpConstant %int 1
  226. )" + kVoidFunction;
  227. spv_target_env env = SPV_ENV_VULKAN_1_1; // need SPIR-V 1.2
  228. CompileSuccessfully(spirv, env);
  229. spvValidatorOptionsSetAllowLocalSizeId(getValidatorOptions(), true);
  230. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  231. }
  232. TEST_F(ValidateMode, GLComputeZeroLocalSizeId) {
  233. const std::string spirv = R"(
  234. OpCapability Shader
  235. OpMemoryModel Logical GLSL450
  236. OpEntryPoint GLCompute %main "main"
  237. OpExecutionModeId %main LocalSizeId %int_1 %int_0 %int_1
  238. %int = OpTypeInt 32 0
  239. %int_1 = OpConstant %int 1
  240. %int_0 = OpConstant %int 0
  241. )" + kVoidFunction;
  242. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  243. CompileSuccessfully(spirv, env);
  244. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  245. EXPECT_THAT(
  246. getDiagnosticString(),
  247. HasSubstr(
  248. "Local Size Id execution mode must not have a product of zero"));
  249. }
  250. TEST_F(ValidateMode, GLComputeZeroSpecLocalSizeId) {
  251. const std::string spirv = R"(
  252. OpCapability Shader
  253. OpMemoryModel Logical GLSL450
  254. OpEntryPoint GLCompute %main "main"
  255. OpExecutionModeId %main LocalSizeId %int_1 %int_0 %int_1
  256. %int = OpTypeInt 32 0
  257. %int_1 = OpConstant %int 1
  258. %int_0 = OpSpecConstant %int 0
  259. )" + kVoidFunction;
  260. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  261. CompileSuccessfully(spirv, env);
  262. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(env));
  263. }
  264. TEST_F(ValidateMode, KernelZeroLocalSizeId) {
  265. const std::string spirv = R"(
  266. OpCapability Addresses
  267. OpCapability Linkage
  268. OpCapability Kernel
  269. OpMemoryModel Physical32 OpenCL
  270. OpEntryPoint Kernel %main "main"
  271. OpExecutionModeId %main LocalSizeId %int_1 %int_0 %int_1
  272. %int = OpTypeInt 32 0
  273. %int_1 = OpConstant %int 1
  274. %int_0 = OpConstant %int 0
  275. )" + kVoidFunction;
  276. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  277. CompileSuccessfully(spirv, env);
  278. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  279. EXPECT_THAT(
  280. getDiagnosticString(),
  281. HasSubstr(
  282. "Local Size Id execution mode must not have a product of zero"));
  283. }
  284. // https://github.com/KhronosGroup/SPIRV-Tools/issues/5939
  285. TEST_F(ValidateMode, KernelZeroLocalSize64) {
  286. const std::string spirv = R"(
  287. OpCapability Kernel
  288. OpCapability Addresses
  289. OpCapability Int64
  290. OpCapability Linkage
  291. OpMemoryModel Physical64 OpenCL
  292. OpEntryPoint Kernel %test "test" %__spirv_BuiltInWorkgroupSize
  293. OpExecutionMode %test ContractionOff
  294. OpDecorate %__spirv_BuiltInWorkgroupSize Constant
  295. OpDecorate %__spirv_BuiltInWorkgroupSize LinkageAttributes "__spirv_BuiltInWorkgroupSize" Import
  296. OpDecorate %__spirv_BuiltInWorkgroupSize BuiltIn WorkgroupSize
  297. %void = OpTypeVoid
  298. %ulong = OpTypeInt 64 0
  299. %v3ulong = OpTypeVector %ulong 3
  300. %_ptr_Input_v3ulong = OpTypePointer Input %v3ulong
  301. %8 = OpTypeFunction %void
  302. %__spirv_BuiltInWorkgroupSize = OpVariable %_ptr_Input_v3ulong Input
  303. %test = OpFunction %void None %8
  304. %entry = OpLabel
  305. %11 = OpLoad %v3ulong %__spirv_BuiltInWorkgroupSize Aligned 1
  306. %12 = OpCompositeExtract %ulong %11 0
  307. OpReturn
  308. OpFunctionEnd
  309. )";
  310. CompileSuccessfully(spirv);
  311. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  312. }
  313. TEST_F(ValidateMode, FragmentOriginLowerLeftVulkan) {
  314. const std::string spirv = R"(
  315. OpCapability Shader
  316. OpMemoryModel Logical GLSL450
  317. OpEntryPoint Fragment %main "main"
  318. OpExecutionMode %main OriginLowerLeft
  319. )" + kVoidFunction;
  320. spv_target_env env = SPV_ENV_VULKAN_1_0;
  321. CompileSuccessfully(spirv, env);
  322. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  323. EXPECT_THAT(getDiagnosticString(),
  324. AnyVUID("VUID-StandaloneSpirv-OriginLowerLeft-04653"));
  325. EXPECT_THAT(getDiagnosticString(),
  326. HasSubstr("In the Vulkan environment, the OriginLowerLeft "
  327. "execution mode must not be used."));
  328. }
  329. TEST_F(ValidateMode, FragmentPixelCenterIntegerVulkan) {
  330. const std::string spirv = R"(
  331. OpCapability Shader
  332. OpMemoryModel Logical GLSL450
  333. OpEntryPoint Fragment %main "main"
  334. OpExecutionMode %main OriginUpperLeft
  335. OpExecutionMode %main PixelCenterInteger
  336. )" + kVoidFunction;
  337. spv_target_env env = SPV_ENV_VULKAN_1_0;
  338. CompileSuccessfully(spirv, env);
  339. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  340. EXPECT_THAT(getDiagnosticString(),
  341. AnyVUID("VUID-StandaloneSpirv-PixelCenterInteger-04654"));
  342. EXPECT_THAT(getDiagnosticString(),
  343. HasSubstr("In the Vulkan environment, the PixelCenterInteger "
  344. "execution mode must not be used."));
  345. }
  346. TEST_F(ValidateMode, GeometryNoOutputMode) {
  347. const std::string spirv = R"(
  348. OpCapability Geometry
  349. OpMemoryModel Logical GLSL450
  350. OpEntryPoint Geometry %main "main"
  351. OpExecutionMode %main InputPoints
  352. )" + kVoidFunction;
  353. CompileSuccessfully(spirv);
  354. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  355. EXPECT_THAT(getDiagnosticString(),
  356. HasSubstr("Geometry execution model entry points must specify "
  357. "exactly one of OutputPoints, OutputLineStrip or "
  358. "OutputTriangleStrip execution modes."));
  359. }
  360. TEST_F(ValidateMode, GeometryNoInputMode) {
  361. const std::string spirv = R"(
  362. OpCapability Geometry
  363. OpMemoryModel Logical GLSL450
  364. OpEntryPoint Geometry %main "main"
  365. OpExecutionMode %main OutputPoints
  366. )" + kVoidFunction;
  367. CompileSuccessfully(spirv);
  368. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  369. EXPECT_THAT(
  370. getDiagnosticString(),
  371. HasSubstr("Geometry execution model entry points must specify exactly "
  372. "one of InputPoints, InputLines, InputLinesAdjacency, "
  373. "Triangles or InputTrianglesAdjacency execution modes."));
  374. }
  375. TEST_F(ValidateMode, FragmentNoOrigin) {
  376. const std::string spirv = R"(
  377. OpCapability Shader
  378. OpMemoryModel Logical GLSL450
  379. OpEntryPoint Fragment %main "main"
  380. )" + kVoidFunction;
  381. CompileSuccessfully(spirv);
  382. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  383. EXPECT_THAT(
  384. getDiagnosticString(),
  385. HasSubstr("Fragment execution model entry points require either an "
  386. "OriginUpperLeft or OriginLowerLeft execution mode."));
  387. }
  388. TEST_F(ValidateMode, FragmentBothOrigins) {
  389. const std::string spirv = R"(
  390. OpCapability Shader
  391. OpMemoryModel Logical GLSL450
  392. OpEntryPoint Fragment %main "main"
  393. OpExecutionMode %main OriginUpperLeft
  394. OpExecutionMode %main OriginLowerLeft
  395. )" + kVoidFunction;
  396. CompileSuccessfully(spirv);
  397. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  398. EXPECT_THAT(
  399. getDiagnosticString(),
  400. HasSubstr("Fragment execution model entry points can only specify one of "
  401. "OriginUpperLeft or OriginLowerLeft execution modes."));
  402. }
  403. TEST_F(ValidateMode, FragmentDepthGreaterAndLess) {
  404. const std::string spirv = R"(
  405. OpCapability Shader
  406. OpMemoryModel Logical GLSL450
  407. OpEntryPoint Fragment %main "main"
  408. OpExecutionMode %main OriginUpperLeft
  409. OpExecutionMode %main DepthGreater
  410. OpExecutionMode %main DepthLess
  411. )" + kVoidFunction;
  412. CompileSuccessfully(spirv);
  413. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  414. EXPECT_THAT(getDiagnosticString(),
  415. HasSubstr("Fragment execution model entry points can specify at "
  416. "most one of DepthGreater, DepthLess or DepthUnchanged "
  417. "execution modes."));
  418. }
  419. TEST_F(ValidateMode, FragmentDepthGreaterAndUnchanged) {
  420. const std::string spirv = R"(
  421. OpCapability Shader
  422. OpMemoryModel Logical GLSL450
  423. OpEntryPoint Fragment %main "main"
  424. OpExecutionMode %main OriginUpperLeft
  425. OpExecutionMode %main DepthGreater
  426. OpExecutionMode %main DepthUnchanged
  427. )" + kVoidFunction;
  428. CompileSuccessfully(spirv);
  429. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  430. EXPECT_THAT(getDiagnosticString(),
  431. HasSubstr("Fragment execution model entry points can specify at "
  432. "most one of DepthGreater, DepthLess or DepthUnchanged "
  433. "execution modes."));
  434. }
  435. TEST_F(ValidateMode, FragmentDepthLessAndUnchanged) {
  436. const std::string spirv = R"(
  437. OpCapability Shader
  438. OpMemoryModel Logical GLSL450
  439. OpEntryPoint Fragment %main "main"
  440. OpExecutionMode %main OriginUpperLeft
  441. OpExecutionMode %main DepthLess
  442. OpExecutionMode %main DepthUnchanged
  443. )" + kVoidFunction;
  444. CompileSuccessfully(spirv);
  445. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  446. EXPECT_THAT(getDiagnosticString(),
  447. HasSubstr("Fragment execution model entry points can specify at "
  448. "most one of DepthGreater, DepthLess or DepthUnchanged "
  449. "execution modes."));
  450. }
  451. TEST_F(ValidateMode, FragmentAllDepths) {
  452. const std::string spirv = R"(
  453. OpCapability Shader
  454. OpMemoryModel Logical GLSL450
  455. OpEntryPoint Fragment %main "main"
  456. OpExecutionMode %main OriginUpperLeft
  457. OpExecutionMode %main DepthGreater
  458. OpExecutionMode %main DepthLess
  459. OpExecutionMode %main DepthUnchanged
  460. )" + kVoidFunction;
  461. CompileSuccessfully(spirv);
  462. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  463. EXPECT_THAT(getDiagnosticString(),
  464. HasSubstr("Fragment execution model entry points can specify at "
  465. "most one of DepthGreater, DepthLess or DepthUnchanged "
  466. "execution modes."));
  467. }
  468. TEST_F(ValidateMode, TessellationControlSpacingEqualAndFractionalOdd) {
  469. const std::string spirv = R"(
  470. OpCapability Tessellation
  471. OpMemoryModel Logical GLSL450
  472. OpEntryPoint TessellationControl %main "main"
  473. OpExecutionMode %main SpacingEqual
  474. OpExecutionMode %main SpacingFractionalOdd
  475. )" + kVoidFunction;
  476. CompileSuccessfully(spirv);
  477. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  478. EXPECT_THAT(getDiagnosticString(),
  479. HasSubstr("Tessellation execution model entry points can specify "
  480. "at most one of SpacingEqual, SpacingFractionalOdd or "
  481. "SpacingFractionalEven execution modes."));
  482. }
  483. TEST_F(ValidateMode, TessellationControlSpacingEqualAndSpacingFractionalEven) {
  484. const std::string spirv = R"(
  485. OpCapability Tessellation
  486. OpMemoryModel Logical GLSL450
  487. OpEntryPoint TessellationControl %main "main"
  488. OpExecutionMode %main SpacingEqual
  489. OpExecutionMode %main SpacingFractionalEven
  490. )" + kVoidFunction;
  491. CompileSuccessfully(spirv);
  492. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  493. EXPECT_THAT(getDiagnosticString(),
  494. HasSubstr("Tessellation execution model entry points can specify "
  495. "at most one of SpacingEqual, SpacingFractionalOdd or "
  496. "SpacingFractionalEven execution modes."));
  497. }
  498. TEST_F(ValidateMode,
  499. TessellationControlSpacingFractionalOddAndSpacingFractionalEven) {
  500. const std::string spirv = R"(
  501. OpCapability Tessellation
  502. OpMemoryModel Logical GLSL450
  503. OpEntryPoint TessellationControl %main "main"
  504. OpExecutionMode %main SpacingFractionalOdd
  505. OpExecutionMode %main SpacingFractionalEven
  506. )" + kVoidFunction;
  507. CompileSuccessfully(spirv);
  508. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  509. EXPECT_THAT(getDiagnosticString(),
  510. HasSubstr("Tessellation execution model entry points can specify "
  511. "at most one of SpacingEqual, SpacingFractionalOdd or "
  512. "SpacingFractionalEven execution modes."));
  513. }
  514. TEST_F(ValidateMode, TessellationControlAllSpacing) {
  515. const std::string spirv = R"(
  516. OpCapability Tessellation
  517. OpMemoryModel Logical GLSL450
  518. OpEntryPoint TessellationControl %main "main"
  519. OpExecutionMode %main SpacingEqual
  520. OpExecutionMode %main SpacingFractionalOdd
  521. OpExecutionMode %main SpacingFractionalEven
  522. )" + kVoidFunction;
  523. CompileSuccessfully(spirv);
  524. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  525. EXPECT_THAT(getDiagnosticString(),
  526. HasSubstr("Tessellation execution model entry points can specify "
  527. "at most one of SpacingEqual, SpacingFractionalOdd or "
  528. "SpacingFractionalEven execution modes."));
  529. }
  530. TEST_F(ValidateMode,
  531. TessellationEvaluationSpacingEqualAndSpacingFractionalOdd) {
  532. const std::string spirv = R"(
  533. OpCapability Tessellation
  534. OpMemoryModel Logical GLSL450
  535. OpEntryPoint TessellationEvaluation %main "main"
  536. OpExecutionMode %main SpacingEqual
  537. OpExecutionMode %main SpacingFractionalOdd
  538. )" + kVoidFunction;
  539. CompileSuccessfully(spirv);
  540. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  541. EXPECT_THAT(getDiagnosticString(),
  542. HasSubstr("Tessellation execution model entry points can specify "
  543. "at most one of SpacingEqual, SpacingFractionalOdd or "
  544. "SpacingFractionalEven execution modes."));
  545. }
  546. TEST_F(ValidateMode,
  547. TessellationEvaluationSpacingEqualAndSpacingFractionalEven) {
  548. const std::string spirv = R"(
  549. OpCapability Tessellation
  550. OpMemoryModel Logical GLSL450
  551. OpEntryPoint TessellationEvaluation %main "main"
  552. OpExecutionMode %main SpacingEqual
  553. OpExecutionMode %main SpacingFractionalEven
  554. )" + kVoidFunction;
  555. CompileSuccessfully(spirv);
  556. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  557. EXPECT_THAT(getDiagnosticString(),
  558. HasSubstr("Tessellation execution model entry points can specify "
  559. "at most one of SpacingEqual, SpacingFractionalOdd or "
  560. "SpacingFractionalEven execution modes."));
  561. }
  562. TEST_F(ValidateMode,
  563. TessellationEvaluationSpacingFractionalOddAndSpacingFractionalEven) {
  564. const std::string spirv = R"(
  565. OpCapability Tessellation
  566. OpMemoryModel Logical GLSL450
  567. OpEntryPoint TessellationEvaluation %main "main"
  568. OpExecutionMode %main SpacingFractionalOdd
  569. OpExecutionMode %main SpacingFractionalEven
  570. )" + kVoidFunction;
  571. CompileSuccessfully(spirv);
  572. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  573. EXPECT_THAT(getDiagnosticString(),
  574. HasSubstr("Tessellation execution model entry points can specify "
  575. "at most one of SpacingEqual, SpacingFractionalOdd or "
  576. "SpacingFractionalEven execution modes."));
  577. }
  578. TEST_F(ValidateMode, TessellationEvaluationAllSpacing) {
  579. const std::string spirv = R"(
  580. OpCapability Tessellation
  581. OpMemoryModel Logical GLSL450
  582. OpEntryPoint TessellationEvaluation %main "main"
  583. OpExecutionMode %main SpacingEqual
  584. OpExecutionMode %main SpacingFractionalOdd
  585. OpExecutionMode %main SpacingFractionalEven
  586. )" + kVoidFunction;
  587. CompileSuccessfully(spirv);
  588. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  589. EXPECT_THAT(getDiagnosticString(),
  590. HasSubstr("Tessellation execution model entry points can specify "
  591. "at most one of SpacingEqual, SpacingFractionalOdd or "
  592. "SpacingFractionalEven execution modes."));
  593. }
  594. TEST_F(ValidateMode, TessellationControlBothVertex) {
  595. const std::string spirv = R"(
  596. OpCapability Tessellation
  597. OpMemoryModel Logical GLSL450
  598. OpEntryPoint TessellationControl %main "main"
  599. OpExecutionMode %main VertexOrderCw
  600. OpExecutionMode %main VertexOrderCcw
  601. )" + kVoidFunction;
  602. CompileSuccessfully(spirv);
  603. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  604. EXPECT_THAT(
  605. getDiagnosticString(),
  606. HasSubstr("Tessellation execution model entry points can specify at most "
  607. "one of VertexOrderCw or VertexOrderCcw execution modes."));
  608. }
  609. TEST_F(ValidateMode, TessellationEvaluationBothVertex) {
  610. const std::string spirv = R"(
  611. OpCapability Tessellation
  612. OpMemoryModel Logical GLSL450
  613. OpEntryPoint TessellationEvaluation %main "main"
  614. OpExecutionMode %main VertexOrderCw
  615. OpExecutionMode %main VertexOrderCcw
  616. )" + kVoidFunction;
  617. CompileSuccessfully(spirv);
  618. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  619. EXPECT_THAT(
  620. getDiagnosticString(),
  621. HasSubstr("Tessellation execution model entry points can specify at most "
  622. "one of VertexOrderCw or VertexOrderCcw execution modes."));
  623. }
  624. using ValidateModeGeometry = spvtest::ValidateBase<std::tuple<
  625. std::tuple<std::string, std::string, std::string, std::string, std::string>,
  626. std::tuple<std::string, std::string, std::string>>>;
  627. TEST_P(ValidateModeGeometry, ExecutionMode) {
  628. std::vector<std::string> input_modes;
  629. std::vector<std::string> output_modes;
  630. input_modes.push_back(std::get<0>(std::get<0>(GetParam())));
  631. input_modes.push_back(std::get<1>(std::get<0>(GetParam())));
  632. input_modes.push_back(std::get<2>(std::get<0>(GetParam())));
  633. input_modes.push_back(std::get<3>(std::get<0>(GetParam())));
  634. input_modes.push_back(std::get<4>(std::get<0>(GetParam())));
  635. output_modes.push_back(std::get<0>(std::get<1>(GetParam())));
  636. output_modes.push_back(std::get<1>(std::get<1>(GetParam())));
  637. output_modes.push_back(std::get<2>(std::get<1>(GetParam())));
  638. std::ostringstream sstr;
  639. sstr << "OpCapability Geometry\n";
  640. sstr << "OpMemoryModel Logical GLSL450\n";
  641. sstr << "OpEntryPoint Geometry %main \"main\"\n";
  642. size_t num_input_modes = 0;
  643. for (auto input : input_modes) {
  644. if (!input.empty()) {
  645. num_input_modes++;
  646. sstr << "OpExecutionMode %main " << input << "\n";
  647. }
  648. }
  649. size_t num_output_modes = 0;
  650. for (auto output : output_modes) {
  651. if (!output.empty()) {
  652. num_output_modes++;
  653. sstr << "OpExecutionMode %main " << output << "\n";
  654. }
  655. }
  656. sstr << "%void = OpTypeVoid\n";
  657. sstr << "%void_fn = OpTypeFunction %void\n";
  658. sstr << "%int = OpTypeInt 32 0\n";
  659. sstr << "%int1 = OpConstant %int 1\n";
  660. sstr << "%main = OpFunction %void None %void_fn\n";
  661. sstr << "%entry = OpLabel\n";
  662. sstr << "OpReturn\n";
  663. sstr << "OpFunctionEnd\n";
  664. CompileSuccessfully(sstr.str());
  665. if (num_input_modes == 1 && num_output_modes == 1) {
  666. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  667. } else {
  668. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  669. if (num_input_modes != 1) {
  670. EXPECT_THAT(getDiagnosticString(),
  671. HasSubstr("Geometry execution model entry points must "
  672. "specify exactly one of InputPoints, InputLines, "
  673. "InputLinesAdjacency, Triangles or "
  674. "InputTrianglesAdjacency execution modes."));
  675. } else {
  676. EXPECT_THAT(
  677. getDiagnosticString(),
  678. HasSubstr("Geometry execution model entry points must specify "
  679. "exactly one of OutputPoints, OutputLineStrip or "
  680. "OutputTriangleStrip execution modes."));
  681. }
  682. }
  683. }
  684. INSTANTIATE_TEST_SUITE_P(
  685. GeometryRequiredModes, ValidateModeGeometry,
  686. Combine(Combine(Values("InputPoints", ""), Values("InputLines", ""),
  687. Values("InputLinesAdjacency", ""), Values("Triangles", ""),
  688. Values("InputTrianglesAdjacency", "")),
  689. Combine(Values("OutputPoints", ""), Values("OutputLineStrip", ""),
  690. Values("OutputTriangleStrip", ""))));
  691. using ValidateModeExecution =
  692. spvtest::ValidateBase<std::tuple<spv_result_t, std::string, std::string,
  693. std::string, spv_target_env>>;
  694. TEST_P(ValidateModeExecution, ExecutionMode) {
  695. const spv_result_t expectation = std::get<0>(GetParam());
  696. const std::string error = std::get<1>(GetParam());
  697. const std::string model = std::get<2>(GetParam());
  698. const std::string mode = std::get<3>(GetParam());
  699. const spv_target_env env = std::get<4>(GetParam());
  700. std::ostringstream sstr;
  701. sstr << "OpCapability Shader\n";
  702. sstr << "OpCapability Geometry\n";
  703. sstr << "OpCapability Tessellation\n";
  704. sstr << "OpCapability TransformFeedback\n";
  705. if (!spvIsVulkanEnv(env)) {
  706. sstr << "OpCapability Kernel\n";
  707. if (env == SPV_ENV_UNIVERSAL_1_3) {
  708. sstr << "OpCapability SubgroupDispatch\n";
  709. } else if (env == SPV_ENV_UNIVERSAL_1_5) {
  710. sstr << "OpCapability TileImageColorReadAccessEXT\n";
  711. sstr << "OpCapability TileImageDepthReadAccessEXT\n";
  712. sstr << "OpCapability TileImageStencilReadAccessEXT\n";
  713. sstr << "OpExtension \"SPV_EXT_shader_tile_image\"\n";
  714. }
  715. }
  716. sstr << "OpMemoryModel Logical GLSL450\n";
  717. sstr << "OpEntryPoint " << model << " %main \"main\"\n";
  718. if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
  719. mode.find("SubgroupsPerWorkgroupId") == 0) {
  720. sstr << "OpExecutionModeId %main " << mode << "\n";
  721. } else {
  722. sstr << "OpExecutionMode %main " << mode << "\n";
  723. }
  724. if (model == "Geometry") {
  725. if (!(mode.find("InputPoints") == 0 || mode.find("InputLines") == 0 ||
  726. mode.find("InputLinesAdjacency") == 0 ||
  727. mode.find("Triangles") == 0 ||
  728. mode.find("InputTrianglesAdjacency") == 0)) {
  729. // Exactly one of the above modes is required for Geometry shaders.
  730. sstr << "OpExecutionMode %main InputPoints\n";
  731. }
  732. if (!(mode.find("OutputPoints") == 0 || mode.find("OutputLineStrip") == 0 ||
  733. mode.find("OutputTriangleStrip") == 0)) {
  734. // Exactly one of the above modes is required for Geometry shaders.
  735. sstr << "OpExecutionMode %main OutputPoints\n";
  736. }
  737. } else if (model == "Fragment") {
  738. if (!(mode.find("OriginUpperLeft") == 0 ||
  739. mode.find("OriginLowerLeft") == 0)) {
  740. // Exactly one of the above modes is required for Fragment shaders.
  741. sstr << "OpExecutionMode %main OriginUpperLeft\n";
  742. }
  743. }
  744. sstr << "%void = OpTypeVoid\n";
  745. sstr << "%void_fn = OpTypeFunction %void\n";
  746. sstr << "%int = OpTypeInt 32 0\n";
  747. sstr << "%int1 = OpConstant %int 1\n";
  748. sstr << "%main = OpFunction %void None %void_fn\n";
  749. sstr << "%entry = OpLabel\n";
  750. sstr << "OpReturn\n";
  751. sstr << "OpFunctionEnd\n";
  752. CompileSuccessfully(sstr.str(), env);
  753. EXPECT_THAT(expectation, ValidateInstructions(env));
  754. if (expectation != SPV_SUCCESS) {
  755. EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
  756. }
  757. }
  758. INSTANTIATE_TEST_SUITE_P(
  759. ValidateModeGeometryOnlyGoodSpv10, ValidateModeExecution,
  760. Combine(Values(SPV_SUCCESS), Values(""), Values("Geometry"),
  761. Values("Invocations 3", "InputPoints", "InputLines",
  762. "InputLinesAdjacency", "InputTrianglesAdjacency",
  763. "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
  764. Values(SPV_ENV_UNIVERSAL_1_0)));
  765. INSTANTIATE_TEST_SUITE_P(
  766. ValidateModeGeometryOnlyBadSpv10, ValidateModeExecution,
  767. Combine(Values(SPV_ERROR_INVALID_DATA),
  768. Values("Execution mode can only be used with the Geometry "
  769. "execution model."),
  770. Values("Fragment", "TessellationEvaluation", "TessellationControl",
  771. "GLCompute", "Vertex", "Kernel"),
  772. Values("Invocations 3", "InputPoints", "InputLines",
  773. "InputLinesAdjacency", "InputTrianglesAdjacency",
  774. "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
  775. Values(SPV_ENV_UNIVERSAL_1_0)));
  776. INSTANTIATE_TEST_SUITE_P(
  777. ValidateModeTessellationOnlyGoodSpv10, ValidateModeExecution,
  778. Combine(Values(SPV_SUCCESS), Values(""),
  779. Values("TessellationControl", "TessellationEvaluation"),
  780. Values("SpacingEqual", "SpacingFractionalEven",
  781. "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
  782. "PointMode", "Quads", "Isolines"),
  783. Values(SPV_ENV_UNIVERSAL_1_0)));
  784. INSTANTIATE_TEST_SUITE_P(
  785. ValidateModeTessellationOnlyBadSpv10, ValidateModeExecution,
  786. Combine(Values(SPV_ERROR_INVALID_DATA),
  787. Values("Execution mode can only be used with a tessellation "
  788. "execution model."),
  789. Values("Fragment", "Geometry", "GLCompute", "Vertex", "Kernel"),
  790. Values("SpacingEqual", "SpacingFractionalEven",
  791. "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
  792. "PointMode", "Quads", "Isolines"),
  793. Values(SPV_ENV_UNIVERSAL_1_0)));
  794. INSTANTIATE_TEST_SUITE_P(ValidateModeGeometryAndTessellationGoodSpv10,
  795. ValidateModeExecution,
  796. Combine(Values(SPV_SUCCESS), Values(""),
  797. Values("TessellationControl",
  798. "TessellationEvaluation", "Geometry"),
  799. Values("Triangles", "OutputVertices 3"),
  800. Values(SPV_ENV_UNIVERSAL_1_0)));
  801. INSTANTIATE_TEST_SUITE_P(
  802. ValidateModeGeometryAndTessellationBadSpv10, ValidateModeExecution,
  803. Combine(Values(SPV_ERROR_INVALID_DATA),
  804. Values("Execution mode can only be used with a Geometry or "
  805. "tessellation execution model."),
  806. Values("Fragment", "GLCompute", "Vertex", "Kernel"),
  807. Values("Triangles", "OutputVertices 3"),
  808. Values(SPV_ENV_UNIVERSAL_1_0)));
  809. INSTANTIATE_TEST_SUITE_P(
  810. ValidateModeFragmentOnlyGoodSpv10, ValidateModeExecution,
  811. Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
  812. Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
  813. "EarlyFragmentTests", "DepthReplacing", "DepthLess",
  814. "DepthUnchanged"),
  815. Values(SPV_ENV_UNIVERSAL_1_0)));
  816. INSTANTIATE_TEST_SUITE_P(
  817. ValidateModeFragmentOnlyBadSpv10, ValidateModeExecution,
  818. Combine(Values(SPV_ERROR_INVALID_DATA),
  819. Values("Execution mode can only be used with the Fragment "
  820. "execution model."),
  821. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  822. "GLCompute", "Vertex", "Kernel"),
  823. Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
  824. "EarlyFragmentTests", "DepthReplacing", "DepthGreater",
  825. "DepthLess", "DepthUnchanged"),
  826. Values(SPV_ENV_UNIVERSAL_1_0)));
  827. INSTANTIATE_TEST_SUITE_P(ValidateModeFragmentOnlyGoodSpv15,
  828. ValidateModeExecution,
  829. Combine(Values(SPV_SUCCESS), Values(""),
  830. Values("Fragment"),
  831. Values("NonCoherentColorAttachmentReadEXT",
  832. "NonCoherentDepthAttachmentReadEXT",
  833. "NonCoherentStencilAttachmentReadEXT"),
  834. Values(SPV_ENV_UNIVERSAL_1_5)));
  835. INSTANTIATE_TEST_SUITE_P(
  836. ValidateModeFragmentOnlyBadSpv15, ValidateModeExecution,
  837. Combine(Values(SPV_ERROR_INVALID_DATA),
  838. Values("Execution mode can only be used with the Fragment "
  839. "execution model."),
  840. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  841. "GLCompute", "Vertex", "Kernel"),
  842. Values("NonCoherentColorAttachmentReadEXT",
  843. "NonCoherentDepthAttachmentReadEXT",
  844. "NonCoherentStencilAttachmentReadEXT"),
  845. Values(SPV_ENV_UNIVERSAL_1_5)));
  846. INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution,
  847. Combine(Values(SPV_SUCCESS), Values(""),
  848. Values("Kernel"),
  849. Values("LocalSizeHint 1 1 1", "VecTypeHint 4",
  850. "ContractionOff",
  851. "LocalSizeHintId %int1 %int1 %int1"),
  852. Values(SPV_ENV_UNIVERSAL_1_3)));
  853. INSTANTIATE_TEST_SUITE_P(
  854. ValidateModeKernelOnlyBadSpv13, ValidateModeExecution,
  855. Combine(
  856. Values(SPV_ERROR_INVALID_DATA),
  857. Values(
  858. "Execution mode can only be used with the Kernel execution model."),
  859. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  860. "GLCompute", "Vertex", "Fragment"),
  861. Values("LocalSizeHint 1 1 1", "VecTypeHint 4", "ContractionOff",
  862. "LocalSizeHintId %int1 %int1 %int1"),
  863. Values(SPV_ENV_UNIVERSAL_1_3)));
  864. INSTANTIATE_TEST_SUITE_P(
  865. ValidateModeGLComputeAndKernelGoodSpv13, ValidateModeExecution,
  866. Combine(Values(SPV_SUCCESS), Values(""), Values("Kernel", "GLCompute"),
  867. Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
  868. Values(SPV_ENV_UNIVERSAL_1_3)));
  869. INSTANTIATE_TEST_SUITE_P(
  870. ValidateModeGLComputeAndKernelBadSpv13, ValidateModeExecution,
  871. Combine(Values(SPV_ERROR_INVALID_DATA),
  872. Values("Execution mode can only be used with a Kernel or GLCompute "
  873. "execution model."),
  874. Values("Geometry", "TessellationControl", "TessellationEvaluation",
  875. "Fragment", "Vertex"),
  876. Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
  877. Values(SPV_ENV_UNIVERSAL_1_3)));
  878. INSTANTIATE_TEST_SUITE_P(
  879. ValidateModeAllGoodSpv13, ValidateModeExecution,
  880. Combine(Values(SPV_SUCCESS), Values(""),
  881. Values("Kernel", "GLCompute", "Geometry", "TessellationControl",
  882. "TessellationEvaluation", "Fragment", "Vertex"),
  883. Values("Xfb", "Initializer", "Finalizer", "SubgroupSize 1",
  884. "SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
  885. Values(SPV_ENV_UNIVERSAL_1_3)));
  886. TEST_F(ValidateModeExecution, MeshNVLocalSize) {
  887. const std::string spirv = R"(
  888. OpCapability Shader
  889. OpCapability MeshShadingNV
  890. OpExtension "SPV_NV_mesh_shader"
  891. OpMemoryModel Logical GLSL450
  892. OpEntryPoint MeshNV %main "main"
  893. OpExecutionMode %main LocalSize 1 1 1
  894. )" + kVoidFunction;
  895. CompileSuccessfully(spirv);
  896. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  897. }
  898. TEST_F(ValidateModeExecution, TaskNVLocalSize) {
  899. const std::string spirv = R"(
  900. OpCapability Shader
  901. OpCapability MeshShadingNV
  902. OpExtension "SPV_NV_mesh_shader"
  903. OpMemoryModel Logical GLSL450
  904. OpEntryPoint TaskNV %main "main"
  905. OpExecutionMode %main LocalSize 1 1 1
  906. )" + kVoidFunction;
  907. CompileSuccessfully(spirv);
  908. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  909. }
  910. TEST_F(ValidateModeExecution, MeshNVOutputPoints) {
  911. const std::string spirv = R"(
  912. OpCapability Shader
  913. OpCapability MeshShadingNV
  914. OpExtension "SPV_NV_mesh_shader"
  915. OpMemoryModel Logical GLSL450
  916. OpEntryPoint MeshNV %main "main"
  917. OpExecutionMode %main OutputPoints
  918. )" + kVoidFunction;
  919. CompileSuccessfully(spirv);
  920. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  921. }
  922. TEST_F(ValidateModeExecution, MeshEXTOutputVertices) {
  923. const std::string spirv = R"(
  924. OpCapability MeshShadingEXT
  925. OpExtension "SPV_EXT_mesh_shader"
  926. %1 = OpExtInstImport "GLSL.std.450"
  927. OpMemoryModel Logical GLSL450
  928. OpEntryPoint MeshEXT %main "main"
  929. OpExecutionMode %main LocalSize 1 1 1
  930. OpExecutionMode %main OutputVertices 3
  931. OpExecutionMode %main OutputPrimitivesNV 1
  932. OpExecutionMode %main OutputTrianglesNV
  933. OpSource GLSL 460
  934. OpSourceExtension "GL_EXT_mesh_shader"
  935. OpName %main "main"
  936. OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
  937. %void = OpTypeVoid
  938. %3 = OpTypeFunction %void
  939. %uint = OpTypeInt 32 0
  940. %uint_3 = OpConstant %uint 3
  941. %uint_1 = OpConstant %uint 1
  942. %v3uint = OpTypeVector %uint 3
  943. %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
  944. %main = OpFunction %void None %3
  945. %5 = OpLabel
  946. OpSetMeshOutputsEXT %uint_3 %uint_1
  947. OpReturn
  948. OpFunctionEnd
  949. )";
  950. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
  951. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  952. }
  953. TEST_F(ValidateModeExecution, VulkanBadMeshEXTOutputVertices) {
  954. const std::string spirv = R"(
  955. OpCapability MeshShadingEXT
  956. OpExtension "SPV_EXT_mesh_shader"
  957. %1 = OpExtInstImport "GLSL.std.450"
  958. OpMemoryModel Logical GLSL450
  959. OpEntryPoint MeshEXT %main "main"
  960. OpExecutionMode %main LocalSize 1 1 1
  961. OpExecutionMode %main OutputVertices 0
  962. OpExecutionMode %main OutputPrimitivesNV 1
  963. OpExecutionMode %main OutputTrianglesNV
  964. OpSource GLSL 460
  965. OpSourceExtension "GL_EXT_mesh_shader"
  966. OpName %main "main"
  967. OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
  968. %void = OpTypeVoid
  969. %3 = OpTypeFunction %void
  970. %uint = OpTypeInt 32 0
  971. %uint_3 = OpConstant %uint 3
  972. %uint_1 = OpConstant %uint 1
  973. %v3uint = OpTypeVector %uint 3
  974. %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
  975. %main = OpFunction %void None %3
  976. %5 = OpLabel
  977. OpSetMeshOutputsEXT %uint_3 %uint_1
  978. OpReturn
  979. OpFunctionEnd
  980. )";
  981. CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
  982. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
  983. EXPECT_THAT(getDiagnosticString(),
  984. AnyVUID("VUID-StandaloneSpirv-MeshEXT-07330"));
  985. }
  986. TEST_F(ValidateModeExecution, VulkanBadMeshEXTOutputOutputPrimitivesEXT) {
  987. const std::string spirv = R"(
  988. OpCapability MeshShadingEXT
  989. OpExtension "SPV_EXT_mesh_shader"
  990. %1 = OpExtInstImport "GLSL.std.450"
  991. OpMemoryModel Logical GLSL450
  992. OpEntryPoint MeshEXT %main "main"
  993. OpExecutionMode %main LocalSize 1 1 1
  994. OpExecutionMode %main OutputVertices 1
  995. OpExecutionMode %main OutputPrimitivesNV 0
  996. OpExecutionMode %main OutputTrianglesNV
  997. OpSource GLSL 460
  998. OpSourceExtension "GL_EXT_mesh_shader"
  999. OpName %main "main"
  1000. OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
  1001. %void = OpTypeVoid
  1002. %3 = OpTypeFunction %void
  1003. %uint = OpTypeInt 32 0
  1004. %uint_3 = OpConstant %uint 3
  1005. %uint_1 = OpConstant %uint 1
  1006. %v3uint = OpTypeVector %uint 3
  1007. %gl_WorkGroupSize = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
  1008. %main = OpFunction %void None %3
  1009. %5 = OpLabel
  1010. OpSetMeshOutputsEXT %uint_3 %uint_1
  1011. OpReturn
  1012. OpFunctionEnd
  1013. )";
  1014. CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
  1015. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
  1016. EXPECT_THAT(getDiagnosticString(),
  1017. AnyVUID("VUID-StandaloneSpirv-MeshEXT-07331"));
  1018. }
  1019. TEST_F(ValidateModeExecution, MeshNVOutputVertices) {
  1020. const std::string spirv = R"(
  1021. OpCapability Shader
  1022. OpCapability MeshShadingNV
  1023. OpExtension "SPV_NV_mesh_shader"
  1024. OpMemoryModel Logical GLSL450
  1025. OpEntryPoint MeshNV %main "main"
  1026. OpExecutionMode %main OutputVertices 42
  1027. )" + kVoidFunction;
  1028. CompileSuccessfully(spirv);
  1029. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  1030. }
  1031. TEST_F(ValidateModeExecution, MeshNVLocalSizeId) {
  1032. const std::string spirv = R"(
  1033. OpCapability Shader
  1034. OpCapability MeshShadingNV
  1035. OpExtension "SPV_NV_mesh_shader"
  1036. OpMemoryModel Logical GLSL450
  1037. OpEntryPoint MeshNV %main "main"
  1038. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  1039. %int = OpTypeInt 32 0
  1040. %int_1 = OpConstant %int 1
  1041. )" + kVoidFunction;
  1042. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1043. CompileSuccessfully(spirv, env);
  1044. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  1045. }
  1046. TEST_F(ValidateModeExecution, TaskNVLocalSizeId) {
  1047. const std::string spirv = R"(
  1048. OpCapability Shader
  1049. OpCapability MeshShadingNV
  1050. OpExtension "SPV_NV_mesh_shader"
  1051. OpMemoryModel Logical GLSL450
  1052. OpEntryPoint TaskNV %main "main"
  1053. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  1054. %int = OpTypeInt 32 0
  1055. %int_1 = OpConstant %int 1
  1056. )" + kVoidFunction;
  1057. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1058. CompileSuccessfully(spirv, env);
  1059. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  1060. }
  1061. TEST_F(ValidateModeExecution, ExecModeSubgroupsPerWorkgroupIdBad) {
  1062. const std::string spirv = R"(
  1063. OpCapability Shader
  1064. OpCapability SubgroupDispatch
  1065. OpMemoryModel Logical GLSL450
  1066. OpEntryPoint Vertex %main "main"
  1067. OpExecutionMode %main SubgroupsPerWorkgroupId %int_1
  1068. %int = OpTypeInt 32 0
  1069. %int_1 = OpConstant %int 1
  1070. )" + kVoidFunction;
  1071. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1072. CompileSuccessfully(spirv, env);
  1073. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  1074. EXPECT_THAT(getDiagnosticString(),
  1075. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  1076. "is an execution mode that takes no Extra Operands"));
  1077. }
  1078. TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdGood) {
  1079. const std::string spirv = R"(
  1080. OpCapability Shader
  1081. OpCapability SubgroupDispatch
  1082. OpMemoryModel Logical GLSL450
  1083. OpEntryPoint Vertex %main "main"
  1084. OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1
  1085. %int = OpTypeInt 32 0
  1086. %int_1 = OpConstant %int 1
  1087. )" + kVoidFunction;
  1088. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1089. CompileSuccessfully(spirv, env);
  1090. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  1091. }
  1092. TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdNonConstantBad) {
  1093. const std::string spirv = R"(
  1094. OpCapability Shader
  1095. OpCapability SubgroupDispatch
  1096. OpMemoryModel Logical GLSL450
  1097. OpEntryPoint Vertex %main "main"
  1098. OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1
  1099. %int = OpTypeInt 32 0
  1100. %int_ptr = OpTypePointer Private %int
  1101. %int_1 = OpVariable %int_ptr Private
  1102. )" + kVoidFunction;
  1103. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1104. CompileSuccessfully(spirv, env);
  1105. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
  1106. EXPECT_THAT(getDiagnosticString(),
  1107. HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
  1108. "constant instructions."));
  1109. }
  1110. TEST_F(ValidateModeExecution, ExecModeLocalSizeHintIdBad) {
  1111. const std::string spirv = R"(
  1112. OpCapability Kernel
  1113. OpCapability Shader
  1114. OpMemoryModel Logical GLSL450
  1115. OpEntryPoint Kernel %main "main"
  1116. OpExecutionMode %main LocalSizeHintId %int_1 %int_1 %int_1
  1117. %int = OpTypeInt 32 0
  1118. %int_1 = OpConstant %int 1
  1119. )" + kVoidFunction;
  1120. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1121. CompileSuccessfully(spirv, env);
  1122. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  1123. EXPECT_THAT(getDiagnosticString(),
  1124. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  1125. "is an execution mode that takes no Extra Operands"));
  1126. }
  1127. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdGood) {
  1128. const std::string spirv = R"(
  1129. OpCapability Kernel
  1130. OpCapability Shader
  1131. OpMemoryModel Logical GLSL450
  1132. OpEntryPoint Kernel %main "main"
  1133. OpExecutionModeId %main LocalSizeHintId %int_1 %int_1 %int_1
  1134. %int = OpTypeInt 32 0
  1135. %int_1 = OpConstant %int 1
  1136. )" + kVoidFunction;
  1137. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1138. CompileSuccessfully(spirv, env);
  1139. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  1140. }
  1141. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdNonConstantBad) {
  1142. const std::string spirv = R"(
  1143. OpCapability Kernel
  1144. OpCapability Shader
  1145. OpMemoryModel Logical GLSL450
  1146. OpEntryPoint Vertex %main "main"
  1147. OpExecutionModeId %main LocalSizeHintId %int_1 %int_1 %int_1
  1148. %int = OpTypeInt 32 0
  1149. %int_ptr = OpTypePointer Private %int
  1150. %int_1 = OpVariable %int_ptr Private
  1151. )" + kVoidFunction;
  1152. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1153. CompileSuccessfully(spirv, env);
  1154. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
  1155. EXPECT_THAT(getDiagnosticString(),
  1156. HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
  1157. "constant instructions."));
  1158. }
  1159. TEST_F(ValidateModeExecution, ExecModeLocalSizeIdBad) {
  1160. const std::string spirv = R"(
  1161. OpCapability Kernel
  1162. OpCapability Shader
  1163. OpMemoryModel Logical GLSL450
  1164. OpEntryPoint Kernel %main "main"
  1165. OpExecutionMode %main LocalSizeId %int_1 %int_1 %int_1
  1166. %int = OpTypeInt 32 0
  1167. %int_1 = OpConstant %int 1
  1168. )" + kVoidFunction;
  1169. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1170. CompileSuccessfully(spirv, env);
  1171. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  1172. EXPECT_THAT(getDiagnosticString(),
  1173. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  1174. "is an execution mode that takes no Extra Operands"));
  1175. }
  1176. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdGood) {
  1177. const std::string spirv = R"(
  1178. OpCapability Kernel
  1179. OpCapability Shader
  1180. OpMemoryModel Logical GLSL450
  1181. OpEntryPoint Kernel %main "main"
  1182. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  1183. %int = OpTypeInt 32 0
  1184. %int_1 = OpConstant %int 1
  1185. )" + kVoidFunction;
  1186. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1187. CompileSuccessfully(spirv, env);
  1188. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  1189. }
  1190. TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdNonConstantBad) {
  1191. const std::string spirv = R"(
  1192. OpCapability Kernel
  1193. OpCapability Shader
  1194. OpMemoryModel Logical GLSL450
  1195. OpEntryPoint Vertex %main "main"
  1196. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  1197. %int = OpTypeInt 32 0
  1198. %int_ptr = OpTypePointer Private %int
  1199. %int_1 = OpVariable %int_ptr Private
  1200. )" + kVoidFunction;
  1201. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  1202. CompileSuccessfully(spirv, env);
  1203. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
  1204. EXPECT_THAT(getDiagnosticString(),
  1205. HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
  1206. "constant instructions."));
  1207. }
  1208. using AllowMultipleExecutionModes = spvtest::ValidateBase<std::string>;
  1209. TEST_P(AllowMultipleExecutionModes, DifferentOperand) {
  1210. const std::string mode = GetParam();
  1211. const std::string spirv = R"(
  1212. OpCapability Shader
  1213. OpCapability DenormPreserve
  1214. OpCapability DenormFlushToZero
  1215. OpCapability SignedZeroInfNanPreserve
  1216. OpCapability RoundingModeRTE
  1217. OpCapability RoundingModeRTZ
  1218. OpExtension "SPV_KHR_float_controls"
  1219. OpMemoryModel Logical GLSL450
  1220. OpEntryPoint GLCompute %main "main"
  1221. OpExecutionMode %main LocalSize 1 1 1
  1222. OpExecutionMode %main )" + mode +
  1223. R"( 16
  1224. OpExecutionMode %main )" + mode +
  1225. R"( 32
  1226. %void = OpTypeVoid
  1227. %void_fn = OpTypeFunction %void
  1228. %main = OpFunction %void None %void_fn
  1229. %entry = OpLabel
  1230. OpReturn
  1231. OpFunctionEnd
  1232. )";
  1233. CompileSuccessfully(spirv);
  1234. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
  1235. }
  1236. TEST_P(AllowMultipleExecutionModes, SameOperand) {
  1237. const std::string mode = GetParam();
  1238. const std::string spirv = R"(
  1239. OpCapability Shader
  1240. OpCapability DenormPreserve
  1241. OpCapability DenormFlushToZero
  1242. OpCapability SignedZeroInfNanPreserve
  1243. OpCapability RoundingModeRTE
  1244. OpCapability RoundingModeRTZ
  1245. OpExtension "SPV_KHR_float_controls"
  1246. OpMemoryModel Logical GLSL450
  1247. OpEntryPoint GLCompute %main "main"
  1248. OpExecutionMode %main LocalSize 1 1 1
  1249. OpExecutionMode %main )" + mode +
  1250. R"( 32
  1251. OpExecutionMode %main )" + mode +
  1252. R"( 32
  1253. %void = OpTypeVoid
  1254. %void_fn = OpTypeFunction %void
  1255. %main = OpFunction %void None %void_fn
  1256. %entry = OpLabel
  1257. OpReturn
  1258. OpFunctionEnd
  1259. )";
  1260. CompileSuccessfully(spirv);
  1261. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1262. EXPECT_THAT(getDiagnosticString(),
  1263. HasSubstr("execution mode must not be specified multiple times "
  1264. "for the same entry point and operands"));
  1265. }
  1266. INSTANTIATE_TEST_SUITE_P(MultipleFloatControlsExecModes,
  1267. AllowMultipleExecutionModes,
  1268. Values("DenormPreserve", "DenormFlushToZero",
  1269. "SignedZeroInfNanPreserve", "RoundingModeRTE",
  1270. "RoundingModeRTZ"));
  1271. using MultipleExecModes = spvtest::ValidateBase<std::string>;
  1272. TEST_P(MultipleExecModes, DuplicateMode) {
  1273. const std::string mode = GetParam();
  1274. const std::string spirv = R"(
  1275. OpCapability Shader
  1276. OpMemoryModel Logical GLSL450
  1277. OpEntryPoint Fragment %main "main"
  1278. OpExecutionMode %main OriginUpperLeft
  1279. OpExecutionMode %main )" + mode +
  1280. R"(
  1281. OpExecutionMode %main )" + mode +
  1282. R"(
  1283. %void = OpTypeVoid
  1284. %void_fn = OpTypeFunction %void
  1285. %main = OpFunction %void None %void_fn
  1286. %entry = OpLabel
  1287. OpReturn
  1288. OpFunctionEnd
  1289. )";
  1290. CompileSuccessfully(spirv);
  1291. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1292. EXPECT_THAT(getDiagnosticString(),
  1293. HasSubstr("execution mode must not be specified multiple times "
  1294. "per entry point"));
  1295. }
  1296. INSTANTIATE_TEST_SUITE_P(MultipleFragmentExecMode, MultipleExecModes,
  1297. Values("DepthReplacing", "DepthGreater", "DepthLess",
  1298. "DepthUnchanged"));
  1299. TEST_F(ValidateMode, FloatControls2FPFastMathDefaultSameOperand) {
  1300. const std::string spirv = R"(
  1301. OpCapability Shader
  1302. OpCapability FloatControls2
  1303. OpExtension "SPV_KHR_float_controls2"
  1304. OpMemoryModel Logical GLSL450
  1305. OpEntryPoint GLCompute %main "main"
  1306. OpExecutionMode %main LocalSize 1 1 1
  1307. OpExecutionModeId %main FPFastMathDefault %float %none
  1308. OpExecutionModeId %main FPFastMathDefault %float %none
  1309. %void = OpTypeVoid
  1310. %float = OpTypeFloat 32
  1311. %int = OpTypeInt 32 0
  1312. %none = OpConstant %int 0
  1313. %void_fn = OpTypeFunction %void
  1314. %main = OpFunction %void None %void_fn
  1315. %entry = OpLabel
  1316. OpReturn
  1317. OpFunctionEnd
  1318. )";
  1319. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
  1320. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
  1321. EXPECT_THAT(getDiagnosticString(),
  1322. HasSubstr("execution mode must not be specified multiple times "
  1323. "for the same entry point and operands"));
  1324. }
  1325. TEST_F(ValidateMode, FloatControls2FPFastMathDefaultDifferentOperand) {
  1326. const std::string spirv = R"(
  1327. OpCapability Shader
  1328. OpCapability Float16
  1329. OpCapability FloatControls2
  1330. OpExtension "SPV_KHR_float_controls2"
  1331. OpMemoryModel Logical GLSL450
  1332. OpEntryPoint GLCompute %main "main"
  1333. OpExecutionMode %main LocalSize 1 1 1
  1334. OpExecutionModeId %main FPFastMathDefault %float %none
  1335. OpExecutionModeId %main FPFastMathDefault %half %none
  1336. %void = OpTypeVoid
  1337. %float = OpTypeFloat 32
  1338. %int = OpTypeInt 32 0
  1339. %none = OpConstant %int 0
  1340. %half = OpTypeFloat 16
  1341. %void_fn = OpTypeFunction %void
  1342. %main = OpFunction %void None %void_fn
  1343. %entry = OpLabel
  1344. OpReturn
  1345. OpFunctionEnd
  1346. )";
  1347. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
  1348. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
  1349. }
  1350. TEST_F(ValidateMode, FragmentShaderInterlockVertexBad) {
  1351. const std::string spirv = R"(
  1352. OpCapability Shader
  1353. OpCapability FragmentShaderPixelInterlockEXT
  1354. OpExtension "SPV_EXT_fragment_shader_interlock"
  1355. OpMemoryModel Logical GLSL450
  1356. OpEntryPoint Vertex %main "main"
  1357. OpExecutionMode %main PixelInterlockOrderedEXT
  1358. )" + kVoidFunction;
  1359. CompileSuccessfully(spirv);
  1360. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1361. EXPECT_THAT(
  1362. getDiagnosticString(),
  1363. HasSubstr(
  1364. "Execution mode can only be used with the Fragment execution model"));
  1365. }
  1366. TEST_F(ValidateMode, FragmentShaderInterlockTooManyModesBad) {
  1367. const std::string spirv = R"(
  1368. OpCapability Shader
  1369. OpCapability FragmentShaderPixelInterlockEXT
  1370. OpCapability FragmentShaderSampleInterlockEXT
  1371. OpExtension "SPV_EXT_fragment_shader_interlock"
  1372. OpMemoryModel Logical GLSL450
  1373. OpEntryPoint Fragment %main "main"
  1374. OpExecutionMode %main OriginUpperLeft
  1375. OpExecutionMode %main PixelInterlockOrderedEXT
  1376. OpExecutionMode %main SampleInterlockOrderedEXT
  1377. )" + kVoidFunction;
  1378. CompileSuccessfully(spirv);
  1379. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1380. EXPECT_THAT(
  1381. getDiagnosticString(),
  1382. HasSubstr("Fragment execution model entry points can specify at most "
  1383. "one fragment shader interlock execution mode"));
  1384. }
  1385. TEST_F(ValidateMode, FragmentShaderInterlockNoModeBad) {
  1386. const std::string spirv = R"(
  1387. OpCapability Shader
  1388. OpCapability FragmentShaderPixelInterlockEXT
  1389. OpExtension "SPV_EXT_fragment_shader_interlock"
  1390. OpMemoryModel Logical GLSL450
  1391. OpEntryPoint Fragment %main "main"
  1392. OpExecutionMode %main OriginUpperLeft
  1393. %void = OpTypeVoid
  1394. %void_fn = OpTypeFunction %void
  1395. %func = OpFunction %void None %void_fn
  1396. %entryf = OpLabel
  1397. OpBeginInvocationInterlockEXT
  1398. OpEndInvocationInterlockEXT
  1399. OpReturn
  1400. OpFunctionEnd
  1401. %main = OpFunction %void None %void_fn
  1402. %entry = OpLabel
  1403. %1 = OpFunctionCall %void %func
  1404. OpReturn
  1405. OpFunctionEnd
  1406. )";
  1407. CompileSuccessfully(spirv);
  1408. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1409. EXPECT_THAT(
  1410. getDiagnosticString(),
  1411. HasSubstr(
  1412. "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT require a "
  1413. "fragment shader interlock execution mode"));
  1414. }
  1415. TEST_F(ValidateMode, FragmentShaderInterlockGood) {
  1416. const std::string spirv = R"(
  1417. OpCapability Shader
  1418. OpCapability FragmentShaderPixelInterlockEXT
  1419. OpExtension "SPV_EXT_fragment_shader_interlock"
  1420. OpMemoryModel Logical GLSL450
  1421. OpEntryPoint Fragment %main "main"
  1422. OpExecutionMode %main OriginUpperLeft
  1423. OpExecutionMode %main PixelInterlockOrderedEXT
  1424. %void = OpTypeVoid
  1425. %void_fn = OpTypeFunction %void
  1426. %func = OpFunction %void None %void_fn
  1427. %entryf = OpLabel
  1428. OpBeginInvocationInterlockEXT
  1429. OpEndInvocationInterlockEXT
  1430. OpReturn
  1431. OpFunctionEnd
  1432. %main = OpFunction %void None %void_fn
  1433. %entry = OpLabel
  1434. %1 = OpFunctionCall %void %func
  1435. OpReturn
  1436. OpFunctionEnd
  1437. )";
  1438. CompileSuccessfully(spirv);
  1439. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  1440. }
  1441. TEST_F(ValidateMode, FragmentShaderStencilRefFrontTooManyModesBad) {
  1442. const std::string spirv = R"(
  1443. OpCapability Shader
  1444. OpCapability StencilExportEXT
  1445. OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
  1446. OpExtension "SPV_EXT_shader_stencil_export"
  1447. OpMemoryModel Logical GLSL450
  1448. OpEntryPoint Fragment %main "main"
  1449. OpExecutionMode %main OriginUpperLeft
  1450. OpExecutionMode %main EarlyAndLateFragmentTestsAMD
  1451. OpExecutionMode %main StencilRefLessFrontAMD
  1452. OpExecutionMode %main StencilRefGreaterFrontAMD
  1453. )" + kVoidFunction;
  1454. CompileSuccessfully(spirv);
  1455. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1456. EXPECT_THAT(
  1457. getDiagnosticString(),
  1458. HasSubstr("Fragment execution model entry points can specify at most "
  1459. "one of StencilRefUnchangedFrontAMD, "
  1460. "StencilRefLessFrontAMD or StencilRefGreaterFrontAMD "
  1461. "execution modes."));
  1462. }
  1463. TEST_F(ValidateMode, FragmentShaderStencilRefBackTooManyModesBad) {
  1464. const std::string spirv = R"(
  1465. OpCapability Shader
  1466. OpCapability StencilExportEXT
  1467. OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
  1468. OpExtension "SPV_EXT_shader_stencil_export"
  1469. OpMemoryModel Logical GLSL450
  1470. OpEntryPoint Fragment %main "main"
  1471. OpExecutionMode %main OriginUpperLeft
  1472. OpExecutionMode %main EarlyAndLateFragmentTestsAMD
  1473. OpExecutionMode %main StencilRefLessBackAMD
  1474. OpExecutionMode %main StencilRefGreaterBackAMD
  1475. )" + kVoidFunction;
  1476. CompileSuccessfully(spirv);
  1477. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1478. EXPECT_THAT(
  1479. getDiagnosticString(),
  1480. HasSubstr("Fragment execution model entry points can specify at most "
  1481. "one of StencilRefUnchangedBackAMD, "
  1482. "StencilRefLessBackAMD or StencilRefGreaterBackAMD "
  1483. "execution modes."));
  1484. }
  1485. TEST_F(ValidateMode, FragmentShaderStencilRefFrontGood) {
  1486. const std::string spirv = R"(
  1487. OpCapability Shader
  1488. OpCapability StencilExportEXT
  1489. OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
  1490. OpExtension "SPV_EXT_shader_stencil_export"
  1491. OpMemoryModel Logical GLSL450
  1492. OpEntryPoint Fragment %main "main"
  1493. OpExecutionMode %main OriginUpperLeft
  1494. OpExecutionMode %main EarlyAndLateFragmentTestsAMD
  1495. OpExecutionMode %main StencilRefLessFrontAMD
  1496. )" + kVoidFunction;
  1497. CompileSuccessfully(spirv);
  1498. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  1499. }
  1500. TEST_F(ValidateMode, FragmentShaderStencilRefBackGood) {
  1501. const std::string spirv = R"(
  1502. OpCapability Shader
  1503. OpCapability StencilExportEXT
  1504. OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
  1505. OpExtension "SPV_EXT_shader_stencil_export"
  1506. OpMemoryModel Logical GLSL450
  1507. OpEntryPoint Fragment %main "main"
  1508. OpExecutionMode %main OriginUpperLeft
  1509. OpExecutionMode %main EarlyAndLateFragmentTestsAMD
  1510. OpExecutionMode %main StencilRefLessBackAMD
  1511. )" + kVoidFunction;
  1512. CompileSuccessfully(spirv);
  1513. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  1514. }
  1515. TEST_F(ValidateMode, FragmentShaderDemoteVertexBad) {
  1516. const std::string spirv = R"(
  1517. OpCapability Shader
  1518. OpCapability DemoteToHelperInvocationEXT
  1519. OpExtension "SPV_EXT_demote_to_helper_invocation"
  1520. OpMemoryModel Logical GLSL450
  1521. OpEntryPoint Vertex %main "main"
  1522. %bool = OpTypeBool
  1523. %void = OpTypeVoid
  1524. %void_fn = OpTypeFunction %void
  1525. %main = OpFunction %void None %void_fn
  1526. %entry = OpLabel
  1527. OpDemoteToHelperInvocationEXT
  1528. %1 = OpIsHelperInvocationEXT %bool
  1529. OpReturn
  1530. OpFunctionEnd
  1531. )";
  1532. CompileSuccessfully(spirv);
  1533. EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
  1534. EXPECT_THAT(
  1535. getDiagnosticString(),
  1536. HasSubstr(
  1537. "OpDemoteToHelperInvocationEXT requires Fragment execution model"));
  1538. EXPECT_THAT(
  1539. getDiagnosticString(),
  1540. HasSubstr("OpIsHelperInvocationEXT requires Fragment execution model"));
  1541. }
  1542. TEST_F(ValidateMode, FragmentShaderDemoteGood) {
  1543. const std::string spirv = R"(
  1544. OpCapability Shader
  1545. OpCapability DemoteToHelperInvocationEXT
  1546. OpExtension "SPV_EXT_demote_to_helper_invocation"
  1547. OpMemoryModel Logical GLSL450
  1548. OpEntryPoint Fragment %main "main"
  1549. OpExecutionMode %main OriginUpperLeft
  1550. %bool = OpTypeBool
  1551. %void = OpTypeVoid
  1552. %void_fn = OpTypeFunction %void
  1553. %main = OpFunction %void None %void_fn
  1554. %entry = OpLabel
  1555. OpDemoteToHelperInvocationEXT
  1556. %1 = OpIsHelperInvocationEXT %bool
  1557. OpReturn
  1558. OpFunctionEnd
  1559. )";
  1560. CompileSuccessfully(spirv);
  1561. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
  1562. }
  1563. TEST_F(ValidateMode, FragmentShaderDemoteBadType) {
  1564. const std::string spirv = R"(
  1565. OpCapability Shader
  1566. OpCapability DemoteToHelperInvocationEXT
  1567. OpExtension "SPV_EXT_demote_to_helper_invocation"
  1568. OpMemoryModel Logical GLSL450
  1569. OpEntryPoint Fragment %main "main"
  1570. OpExecutionMode %main OriginUpperLeft
  1571. %u32 = OpTypeInt 32 0
  1572. %void = OpTypeVoid
  1573. %void_fn = OpTypeFunction %void
  1574. %main = OpFunction %void None %void_fn
  1575. %entry = OpLabel
  1576. OpDemoteToHelperInvocationEXT
  1577. %1 = OpIsHelperInvocationEXT %u32
  1578. OpReturn
  1579. OpFunctionEnd
  1580. )";
  1581. CompileSuccessfully(spirv);
  1582. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1583. EXPECT_THAT(getDiagnosticString(),
  1584. HasSubstr("Expected bool scalar type as Result Type"));
  1585. }
  1586. TEST_F(ValidateMode, LocalSizeIdVulkan1p3DoesNotRequireOption) {
  1587. const std::string spirv = R"(
  1588. OpCapability Shader
  1589. OpMemoryModel Logical GLSL450
  1590. OpEntryPoint GLCompute %main "main"
  1591. OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
  1592. %void = OpTypeVoid
  1593. %int = OpTypeInt 32 0
  1594. %int_1 = OpConstant %int 1
  1595. %void_fn = OpTypeFunction %void
  1596. %main = OpFunction %void None %void_fn
  1597. %entry = OpLabel
  1598. OpReturn
  1599. OpFunctionEnd
  1600. )";
  1601. CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
  1602. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
  1603. }
  1604. TEST_F(ValidateMode, MaximalReconvergenceRequiresExtension) {
  1605. const std::string spirv = R"(
  1606. OpCapability Shader
  1607. OpMemoryModel Logical GLSL450
  1608. OpEntryPoint GLCompute %main "main"
  1609. OpExecutionMode %main LocalSize 1 1 1
  1610. OpExecutionMode %main MaximallyReconvergesKHR
  1611. %void = OpTypeVoid
  1612. %void_fn = OpTypeFunction %void
  1613. %main = OpFunction %void None %void_fn
  1614. %entry = OpLabel
  1615. OpReturn
  1616. OpFunctionEnd
  1617. )";
  1618. CompileSuccessfully(spirv);
  1619. EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
  1620. EXPECT_THAT(getDiagnosticString(),
  1621. HasSubstr("(6023) requires one of these extensions: "
  1622. "SPV_KHR_maximal_reconvergence "));
  1623. }
  1624. TEST_F(ValidateMode, FPFastMathDefaultNotExecutionModeId) {
  1625. const std::string spirv = R"(
  1626. OpCapability Shader
  1627. OpCapability FloatControls2
  1628. OpExtension "SPV_KHR_float_controls2"
  1629. OpMemoryModel Logical GLSL450
  1630. OpEntryPoint GLCompute %main "main"
  1631. OpExecutionMode %main LocalSize 1 1 1
  1632. OpExecutionMode %main FPFastMathDefault %int_0 %int_0
  1633. %void = OpTypeVoid
  1634. %int = OpTypeInt 32 0
  1635. %int_0 = OpConstant %int 0
  1636. %void_fn = OpTypeFunction %void
  1637. %main = OpFunction %void None %void_fn
  1638. %entry = OpLabel
  1639. OpReturn
  1640. OpFunctionEnd
  1641. )";
  1642. CompileSuccessfully(spirv);
  1643. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
  1644. EXPECT_THAT(getDiagnosticString(),
  1645. HasSubstr("OpExecutionMode is only valid when the Mode operand "
  1646. "is an execution mode that takes no Extra Operands, or "
  1647. "takes Extra Operands that are not id operands"));
  1648. }
  1649. TEST_F(ValidateMode, FPFastMathDefaultNotAType) {
  1650. const std::string spirv = R"(
  1651. OpCapability Shader
  1652. OpCapability FloatControls2
  1653. OpExtension "SPV_KHR_float_controls2"
  1654. OpMemoryModel Logical GLSL450
  1655. OpEntryPoint GLCompute %main "main"
  1656. OpExecutionMode %main LocalSize 1 1 1
  1657. OpExecutionModeId %main FPFastMathDefault %int_0 %int_0
  1658. %void = OpTypeVoid
  1659. %int = OpTypeInt 32 0
  1660. %int_0 = OpConstant %int 0
  1661. %void_fn = OpTypeFunction %void
  1662. %main = OpFunction %void None %void_fn
  1663. %entry = OpLabel
  1664. OpReturn
  1665. OpFunctionEnd
  1666. )";
  1667. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1668. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1669. EXPECT_THAT(
  1670. getDiagnosticString(),
  1671. HasSubstr(
  1672. "The Target Type operand must be a floating-point scalar type"));
  1673. }
  1674. TEST_F(ValidateMode, FPFastMathDefaultNotAFloatType) {
  1675. const std::string spirv = R"(
  1676. OpCapability Shader
  1677. OpCapability FloatControls2
  1678. OpExtension "SPV_KHR_float_controls2"
  1679. OpMemoryModel Logical GLSL450
  1680. OpEntryPoint GLCompute %main "main"
  1681. OpExecutionMode %main LocalSize 1 1 1
  1682. OpExecutionModeId %main FPFastMathDefault %int %int_0
  1683. %void = OpTypeVoid
  1684. %int = OpTypeInt 32 0
  1685. %int_0 = OpConstant %int 0
  1686. %void_fn = OpTypeFunction %void
  1687. %main = OpFunction %void None %void_fn
  1688. %entry = OpLabel
  1689. OpReturn
  1690. OpFunctionEnd
  1691. )";
  1692. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1693. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1694. EXPECT_THAT(
  1695. getDiagnosticString(),
  1696. HasSubstr(
  1697. "The Target Type operand must be a floating-point scalar type"));
  1698. }
  1699. TEST_F(ValidateMode, FPFastMathDefaultNotAFloatScalarType) {
  1700. const std::string spirv = R"(
  1701. OpCapability Shader
  1702. OpCapability FloatControls2
  1703. OpExtension "SPV_KHR_float_controls2"
  1704. OpMemoryModel Logical GLSL450
  1705. OpEntryPoint GLCompute %main "main"
  1706. OpExecutionMode %main LocalSize 1 1 1
  1707. OpExecutionModeId %main FPFastMathDefault %float2 %int_0
  1708. %void = OpTypeVoid
  1709. %int = OpTypeInt 32 0
  1710. %int_0 = OpConstant %int 0
  1711. %float = OpTypeFloat 32
  1712. %float2 = OpTypeVector %float 2
  1713. %void_fn = OpTypeFunction %void
  1714. %main = OpFunction %void None %void_fn
  1715. %entry = OpLabel
  1716. OpReturn
  1717. OpFunctionEnd
  1718. )";
  1719. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1720. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1721. EXPECT_THAT(
  1722. getDiagnosticString(),
  1723. HasSubstr(
  1724. "The Target Type operand must be a floating-point scalar type"));
  1725. }
  1726. TEST_F(ValidateMode, FPFastMathDefaultSpecConstant) {
  1727. const std::string spirv = R"(
  1728. OpCapability Shader
  1729. OpCapability FloatControls2
  1730. OpExtension "SPV_KHR_float_controls2"
  1731. OpMemoryModel Logical GLSL450
  1732. OpEntryPoint GLCompute %main "main"
  1733. OpExecutionMode %main LocalSize 1 1 1
  1734. OpExecutionModeId %main FPFastMathDefault %float %int_0
  1735. %void = OpTypeVoid
  1736. %int = OpTypeInt 32 0
  1737. %int_0 = OpSpecConstant %int 0
  1738. %float = OpTypeFloat 32
  1739. %void_fn = OpTypeFunction %void
  1740. %main = OpFunction %void None %void_fn
  1741. %entry = OpLabel
  1742. OpReturn
  1743. OpFunctionEnd
  1744. )";
  1745. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1746. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1747. EXPECT_THAT(getDiagnosticString(),
  1748. HasSubstr("The Fast Math Default operand must be a "
  1749. "non-specialization constant"));
  1750. }
  1751. TEST_F(ValidateMode, FPFastMathDefaultInvalidMask) {
  1752. const std::string spirv = R"(
  1753. OpCapability Shader
  1754. OpCapability FloatControls2
  1755. OpExtension "SPV_KHR_float_controls2"
  1756. OpMemoryModel Logical GLSL450
  1757. OpEntryPoint GLCompute %main "main"
  1758. OpExecutionMode %main LocalSize 1 1 1
  1759. OpExecutionModeId %main FPFastMathDefault %float %constant
  1760. %void = OpTypeVoid
  1761. %int = OpTypeInt 32 0
  1762. %constant = OpConstant %int 524288
  1763. %float = OpTypeFloat 32
  1764. %void_fn = OpTypeFunction %void
  1765. %main = OpFunction %void None %void_fn
  1766. %entry = OpLabel
  1767. OpReturn
  1768. OpFunctionEnd
  1769. )";
  1770. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1771. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1772. EXPECT_THAT(
  1773. getDiagnosticString(),
  1774. HasSubstr("The Fast Math Default operand is an invalid bitmask value"));
  1775. }
  1776. TEST_F(ValidateMode, FPFastMathDefaultContainsFast) {
  1777. const std::string spirv = R"(
  1778. OpCapability Shader
  1779. OpCapability FloatControls2
  1780. OpExtension "SPV_KHR_float_controls2"
  1781. OpMemoryModel Logical GLSL450
  1782. OpEntryPoint GLCompute %main "main"
  1783. OpExecutionMode %main LocalSize 1 1 1
  1784. OpExecutionModeId %main FPFastMathDefault %float %constant
  1785. %void = OpTypeVoid
  1786. %int = OpTypeInt 32 0
  1787. %constant = OpConstant %int 16
  1788. %float = OpTypeFloat 32
  1789. %void_fn = OpTypeFunction %void
  1790. %main = OpFunction %void None %void_fn
  1791. %entry = OpLabel
  1792. OpReturn
  1793. OpFunctionEnd
  1794. )";
  1795. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1796. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1797. EXPECT_THAT(getDiagnosticString(),
  1798. HasSubstr("The Fast Math Default operand must not include Fast"));
  1799. }
  1800. TEST_F(ValidateMode, FPFastMathDefaultAllowTransformMissingAllowReassoc) {
  1801. const std::string spirv = R"(
  1802. OpCapability Shader
  1803. OpCapability FloatControls2
  1804. OpExtension "SPV_KHR_float_controls2"
  1805. OpMemoryModel Logical GLSL450
  1806. OpEntryPoint GLCompute %main "main"
  1807. OpExecutionMode %main LocalSize 1 1 1
  1808. OpExecutionModeId %main FPFastMathDefault %float %constant
  1809. %void = OpTypeVoid
  1810. %int = OpTypeInt 32 0
  1811. %constant = OpConstant %int 327680
  1812. %float = OpTypeFloat 32
  1813. %void_fn = OpTypeFunction %void
  1814. %main = OpFunction %void None %void_fn
  1815. %entry = OpLabel
  1816. OpReturn
  1817. OpFunctionEnd
  1818. )";
  1819. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1820. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1821. EXPECT_THAT(
  1822. getDiagnosticString(),
  1823. HasSubstr("The Fast Math Default operand must include AllowContract and "
  1824. "AllowReassoc when AllowTransform is specified"));
  1825. }
  1826. TEST_F(ValidateMode, FPFastMathDefaultAllowTransformMissingAllowContract) {
  1827. const std::string spirv = R"(
  1828. OpCapability Shader
  1829. OpCapability FloatControls2
  1830. OpExtension "SPV_KHR_float_controls2"
  1831. OpMemoryModel Logical GLSL450
  1832. OpEntryPoint GLCompute %main "main"
  1833. OpExecutionMode %main LocalSize 1 1 1
  1834. OpExecutionModeId %main FPFastMathDefault %float %constant
  1835. %void = OpTypeVoid
  1836. %int = OpTypeInt 32 0
  1837. %constant = OpConstant %int 393216
  1838. %float = OpTypeFloat 32
  1839. %void_fn = OpTypeFunction %void
  1840. %main = OpFunction %void None %void_fn
  1841. %entry = OpLabel
  1842. OpReturn
  1843. OpFunctionEnd
  1844. )";
  1845. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1846. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1847. EXPECT_THAT(
  1848. getDiagnosticString(),
  1849. HasSubstr("The Fast Math Default operand must include AllowContract and "
  1850. "AllowReassoc when AllowTransform is specified"));
  1851. }
  1852. TEST_F(ValidateMode, FPFastMathDefaultAllowTransformMissingContractAndReassoc) {
  1853. const std::string spirv = R"(
  1854. OpCapability Shader
  1855. OpCapability FloatControls2
  1856. OpExtension "SPV_KHR_float_controls2"
  1857. OpMemoryModel Logical GLSL450
  1858. OpEntryPoint GLCompute %main "main"
  1859. OpExecutionMode %main LocalSize 1 1 1
  1860. OpExecutionModeId %main FPFastMathDefault %float %constant
  1861. %void = OpTypeVoid
  1862. %int = OpTypeInt 32 0
  1863. %constant = OpConstant %int 262144
  1864. %float = OpTypeFloat 32
  1865. %void_fn = OpTypeFunction %void
  1866. %main = OpFunction %void None %void_fn
  1867. %entry = OpLabel
  1868. OpReturn
  1869. OpFunctionEnd
  1870. )";
  1871. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1872. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1873. EXPECT_THAT(
  1874. getDiagnosticString(),
  1875. HasSubstr("The Fast Math Default operand must include AllowContract and "
  1876. "AllowReassoc when AllowTransform is specified"));
  1877. }
  1878. TEST_F(ValidateMode, FPFastMathDefaultSignedZeroInfNanPreserve) {
  1879. const std::string spirv = R"(
  1880. OpCapability Shader
  1881. OpCapability FloatControls2
  1882. OpCapability SignedZeroInfNanPreserve
  1883. OpExtension "SPV_KHR_float_controls2"
  1884. OpExtension "SPV_KHR_float_controls"
  1885. OpMemoryModel Logical GLSL450
  1886. OpEntryPoint GLCompute %main "main"
  1887. OpExecutionMode %main LocalSize 1 1 1
  1888. OpExecutionModeId %main FPFastMathDefault %float %constant
  1889. OpExecutionMode %main SignedZeroInfNanPreserve 32
  1890. %void = OpTypeVoid
  1891. %int = OpTypeInt 32 0
  1892. %constant = OpConstant %int 0
  1893. %float = OpTypeFloat 32
  1894. %void_fn = OpTypeFunction %void
  1895. %main = OpFunction %void None %void_fn
  1896. %entry = OpLabel
  1897. OpReturn
  1898. OpFunctionEnd
  1899. )";
  1900. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1901. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1902. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1903. EXPECT_THAT(
  1904. getDiagnosticString(),
  1905. HasSubstr("FPFastMathDefault and SignedZeroInfNanPreserve execution "
  1906. "modes cannot be applied to the same entry point"));
  1907. }
  1908. TEST_F(ValidateMode, FPFastMathDefaultConractionOff) {
  1909. const std::string spirv = R"(
  1910. OpCapability Kernel
  1911. OpCapability Addresses
  1912. OpCapability FloatControls2
  1913. OpCapability SignedZeroInfNanPreserve
  1914. OpExtension "SPV_KHR_float_controls2"
  1915. OpExtension "SPV_KHR_float_controls"
  1916. OpMemoryModel Physical64 OpenCL
  1917. OpEntryPoint Kernel %main "main"
  1918. OpExecutionModeId %main FPFastMathDefault %float %constant
  1919. OpExecutionMode %main ContractionOff
  1920. %void = OpTypeVoid
  1921. %int = OpTypeInt 32 0
  1922. %constant = OpConstant %int 0
  1923. %float = OpTypeFloat 32
  1924. %void_fn = OpTypeFunction %void
  1925. %main = OpFunction %void None %void_fn
  1926. %entry = OpLabel
  1927. OpReturn
  1928. OpFunctionEnd
  1929. )";
  1930. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1931. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1932. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1933. EXPECT_THAT(getDiagnosticString(),
  1934. HasSubstr("FPFastMathDefault and ContractionOff execution modes "
  1935. "cannot be applied to the same entry point"));
  1936. }
  1937. TEST_F(ValidateMode, FPFastMathDefaultNoContractionNotInCallTree) {
  1938. const std::string spirv = R"(
  1939. OpCapability Shader
  1940. OpCapability FloatControls2
  1941. OpExtension "SPV_KHR_float_controls2"
  1942. OpMemoryModel Logical GLSL450
  1943. OpEntryPoint GLCompute %main "main"
  1944. OpExecutionModeId %main FPFastMathDefault %float %constant
  1945. OpExecutionMode %main LocalSize 1 1 1
  1946. OpDecorate %add NoContraction
  1947. %void = OpTypeVoid
  1948. %int = OpTypeInt 32 0
  1949. %constant = OpConstant %int 0
  1950. %float = OpTypeFloat 32
  1951. %zero = OpConstant %float 0
  1952. %void_fn = OpTypeFunction %void
  1953. %main = OpFunction %void None %void_fn
  1954. %entry = OpLabel
  1955. OpReturn
  1956. OpFunctionEnd
  1957. %func = OpFunction %void None %void_fn
  1958. %func_entry = OpLabel
  1959. %add = OpFAdd %float %zero %zero
  1960. OpReturn
  1961. OpFunctionEnd
  1962. )";
  1963. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1964. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1965. }
  1966. TEST_F(ValidateMode, FPFastMathDefaultNoContractionInCallTree) {
  1967. const std::string spirv = R"(
  1968. OpCapability Shader
  1969. OpCapability FloatControls2
  1970. OpExtension "SPV_KHR_float_controls2"
  1971. OpMemoryModel Logical GLSL450
  1972. OpEntryPoint GLCompute %main "main"
  1973. OpExecutionModeId %main FPFastMathDefault %float %constant
  1974. OpExecutionMode %main LocalSize 1 1 1
  1975. OpDecorate %add NoContraction
  1976. %void = OpTypeVoid
  1977. %int = OpTypeInt 32 0
  1978. %constant = OpConstant %int 0
  1979. %float = OpTypeFloat 32
  1980. %zero = OpConstant %float 0
  1981. %void_fn = OpTypeFunction %void
  1982. %main = OpFunction %void None %void_fn
  1983. %entry = OpLabel
  1984. %call = OpFunctionCall %void %func
  1985. OpReturn
  1986. OpFunctionEnd
  1987. %func = OpFunction %void None %void_fn
  1988. %func_entry = OpLabel
  1989. %add = OpFAdd %float %zero %zero
  1990. OpReturn
  1991. OpFunctionEnd
  1992. )";
  1993. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  1994. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  1995. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  1996. EXPECT_THAT(getDiagnosticString(),
  1997. HasSubstr("NoContraction cannot be used by an entry point with "
  1998. "the FPFastMathDefault execution mode"));
  1999. }
  2000. TEST_F(ValidateMode, FPFastMathDefaultNoContractionInCallTree2) {
  2001. const std::string spirv = R"(
  2002. OpCapability Shader
  2003. OpCapability Kernel
  2004. OpCapability Addresses
  2005. OpCapability FloatControls2
  2006. OpExtension "SPV_KHR_float_controls2"
  2007. OpMemoryModel Physical64 OpenCL
  2008. OpEntryPoint Kernel %main "main"
  2009. OpExecutionModeId %main FPFastMathDefault %float %constant
  2010. OpDecorate %const NoContraction
  2011. %void = OpTypeVoid
  2012. %int = OpTypeInt 32 0
  2013. %constant = OpConstant %int 0
  2014. %float = OpTypeFloat 32
  2015. %zero = OpConstant %float 0
  2016. %const = OpSpecConstantOp %float FAdd %zero %zero
  2017. %void_fn = OpTypeFunction %void
  2018. %main = OpFunction %void None %void_fn
  2019. %entry = OpLabel
  2020. %call = OpFunctionCall %void %func
  2021. OpReturn
  2022. OpFunctionEnd
  2023. %func = OpFunction %void None %void_fn
  2024. %func_entry = OpLabel
  2025. %add = OpFAdd %float %const %zero
  2026. OpReturn
  2027. OpFunctionEnd
  2028. )";
  2029. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  2030. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  2031. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  2032. EXPECT_THAT(getDiagnosticString(),
  2033. HasSubstr("NoContraction cannot be used by an entry point with "
  2034. "the FPFastMathDefault execution mode"));
  2035. }
  2036. TEST_F(ValidateMode, FPFastMathDefaultFastMathFastNotInCallTree) {
  2037. const std::string spirv = R"(
  2038. OpCapability Shader
  2039. OpCapability FloatControls2
  2040. OpExtension "SPV_KHR_float_controls2"
  2041. OpMemoryModel Logical GLSL450
  2042. OpEntryPoint GLCompute %main "main"
  2043. OpExecutionModeId %main FPFastMathDefault %float %constant
  2044. OpExecutionMode %main LocalSize 1 1 1
  2045. OpDecorate %add FPFastMathMode Fast
  2046. %void = OpTypeVoid
  2047. %int = OpTypeInt 32 0
  2048. %constant = OpConstant %int 0
  2049. %float = OpTypeFloat 32
  2050. %zero = OpConstant %float 0
  2051. %void_fn = OpTypeFunction %void
  2052. %main = OpFunction %void None %void_fn
  2053. %entry = OpLabel
  2054. OpReturn
  2055. OpFunctionEnd
  2056. %func = OpFunction %void None %void_fn
  2057. %func_entry = OpLabel
  2058. %add = OpFAdd %float %zero %zero
  2059. OpReturn
  2060. OpFunctionEnd
  2061. )";
  2062. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  2063. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  2064. }
  2065. TEST_F(ValidateMode, FPFastMathDefaultFastMathFastInCallTree) {
  2066. const std::string spirv = R"(
  2067. OpCapability Shader
  2068. OpCapability FloatControls2
  2069. OpExtension "SPV_KHR_float_controls2"
  2070. OpMemoryModel Logical GLSL450
  2071. OpEntryPoint GLCompute %main "main"
  2072. OpExecutionModeId %main FPFastMathDefault %float %constant
  2073. OpExecutionMode %main LocalSize 1 1 1
  2074. OpDecorate %add FPFastMathMode Fast
  2075. %void = OpTypeVoid
  2076. %int = OpTypeInt 32 0
  2077. %constant = OpConstant %int 0
  2078. %float = OpTypeFloat 32
  2079. %zero = OpConstant %float 0
  2080. %void_fn = OpTypeFunction %void
  2081. %main = OpFunction %void None %void_fn
  2082. %entry = OpLabel
  2083. %call = OpFunctionCall %void %func
  2084. OpReturn
  2085. OpFunctionEnd
  2086. %func = OpFunction %void None %void_fn
  2087. %func_entry = OpLabel
  2088. %add = OpFAdd %float %zero %zero
  2089. OpReturn
  2090. OpFunctionEnd
  2091. )";
  2092. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  2093. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  2094. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  2095. EXPECT_THAT(getDiagnosticString(),
  2096. HasSubstr("FPFastMathMode Fast cannot be used by an entry point "
  2097. "with the FPFastMathDefault execution mode"));
  2098. }
  2099. TEST_F(ValidateMode, FPFastMathDefaultFastMathFastInCallTree2) {
  2100. const std::string spirv = R"(
  2101. OpCapability Kernel
  2102. OpCapability Addresses
  2103. OpCapability FloatControls2
  2104. OpExtension "SPV_KHR_float_controls2"
  2105. OpMemoryModel Physical64 OpenCL
  2106. OpEntryPoint Kernel %main "main"
  2107. OpExecutionModeId %main FPFastMathDefault %float %constant
  2108. OpDecorate %const FPFastMathMode Fast
  2109. %void = OpTypeVoid
  2110. %int = OpTypeInt 32 0
  2111. %constant = OpConstant %int 0
  2112. %float = OpTypeFloat 32
  2113. %zero = OpConstant %float 0
  2114. %const = OpSpecConstantOp %float FAdd %zero %zero
  2115. %void_fn = OpTypeFunction %void
  2116. %main = OpFunction %void None %void_fn
  2117. %entry = OpLabel
  2118. %call = OpFunctionCall %void %func
  2119. OpReturn
  2120. OpFunctionEnd
  2121. %func = OpFunction %void None %void_fn
  2122. %func_entry = OpLabel
  2123. %add = OpFAdd %float %const %zero
  2124. OpReturn
  2125. OpFunctionEnd
  2126. )";
  2127. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  2128. EXPECT_EQ(SPV_ERROR_INVALID_DATA,
  2129. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  2130. EXPECT_THAT(getDiagnosticString(),
  2131. HasSubstr("FPFastMathMode Fast cannot be used by an entry point "
  2132. "with the FPFastMathDefault execution mode"));
  2133. }
  2134. TEST_F(ValidateMode, FragmentShaderRequireFullQuadsKHR) {
  2135. const std::string spirv = R"(
  2136. OpCapability Shader
  2137. OpCapability GroupNonUniform
  2138. OpCapability GroupNonUniformVote
  2139. OpCapability GroupNonUniformBallot
  2140. OpCapability QuadControlKHR
  2141. OpExtension "SPV_KHR_quad_control"
  2142. %1 = OpExtInstImport "GLSL.std.450"
  2143. OpMemoryModel Logical GLSL450
  2144. OpEntryPoint GLCompute %4 "main"
  2145. OpExecutionMode %4 OriginUpperLeft
  2146. OpExecutionMode %4 RequireFullQuadsKHR
  2147. OpDecorate %17 Location 0
  2148. OpDecorate %31 BuiltIn HelperInvocation
  2149. OpDecorate %40 Location 0
  2150. OpDecorate %44 DescriptorSet 0
  2151. OpDecorate %44 Binding 0
  2152. %2 = OpTypeVoid
  2153. %3 = OpTypeFunction %2
  2154. %6 = OpTypeInt 32 0
  2155. %7 = OpTypeVector %6 4
  2156. %8 = OpTypePointer Function %7
  2157. %10 = OpTypeBool
  2158. %11 = OpConstantTrue %10
  2159. %12 = OpConstant %6 7
  2160. %14 = OpTypeFloat 32
  2161. %15 = OpTypeVector %14 4
  2162. %16 = OpTypePointer Output %15
  2163. %17 = OpVariable %16 Output
  2164. %18 = OpConstant %14 1
  2165. %19 = OpConstant %14 0
  2166. %20 = OpConstantComposite %15 %18 %19 %19 %18
  2167. %23 = OpConstant %6 4
  2168. %27 = OpConstant %6 1
  2169. %28 = OpTypePointer Output %14
  2170. %30 = OpTypePointer Input %10
  2171. %31 = OpVariable %30 Input
  2172. %36 = OpConstant %6 2
  2173. %38 = OpTypeVector %14 2
  2174. %39 = OpTypePointer Input %38
  2175. %40 = OpVariable %39 Input
  2176. %41 = OpTypeImage %14 2D 0 0 0 1 Unknown
  2177. %42 = OpTypeSampledImage %41
  2178. %43 = OpTypePointer UniformConstant %42
  2179. %44 = OpVariable %43 UniformConstant
  2180. %4 = OpFunction %2 None %3
  2181. %5 = OpLabel
  2182. %9 = OpVariable %8 Function
  2183. %13 = OpGroupNonUniformBallot %7 %12 %11
  2184. OpStore %9 %13
  2185. OpStore %17 %20
  2186. %21 = OpLoad %7 %9
  2187. %22 = OpGroupNonUniformBallotBitCount %6 %12 Reduce %21
  2188. %24 = OpIEqual %10 %22 %23
  2189. OpSelectionMerge %26 None
  2190. OpBranchConditional %24 %25 %26
  2191. %25 = OpLabel
  2192. %29 = OpAccessChain %28 %17 %27
  2193. OpStore %29 %18
  2194. OpBranch %26
  2195. %26 = OpLabel
  2196. %32 = OpLoad %10 %31
  2197. %33 = OpGroupNonUniformAny %10 %12 %32
  2198. OpSelectionMerge %35 None
  2199. OpBranchConditional %33 %34 %35
  2200. %34 = OpLabel
  2201. %37 = OpAccessChain %28 %17 %36
  2202. OpStore %37 %18
  2203. OpBranch %35
  2204. %35 = OpLabel
  2205. OpReturn
  2206. OpFunctionEnd
  2207. )";
  2208. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  2209. EXPECT_THAT(SPV_ERROR_INVALID_DATA,
  2210. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  2211. EXPECT_THAT(
  2212. getDiagnosticString(),
  2213. HasSubstr(
  2214. "Execution mode can only be used with the Fragment execution model"));
  2215. }
  2216. TEST_F(ValidateMode, FragmentShaderQuadDerivativesKHR) {
  2217. const std::string spirv = R"(
  2218. OpCapability Shader
  2219. OpCapability GroupNonUniform
  2220. OpCapability GroupNonUniformVote
  2221. OpCapability QuadControlKHR
  2222. OpExtension "SPV_KHR_quad_control"
  2223. %1 = OpExtInstImport "GLSL.std.450"
  2224. OpMemoryModel Logical GLSL450
  2225. OpEntryPoint GLCompute %4 "main"
  2226. OpExecutionMode %4 OriginUpperLeft
  2227. OpExecutionMode %4 QuadDerivativesKHR
  2228. OpDecorate %12 BuiltIn FragCoord
  2229. OpDecorate %41 Location 0
  2230. OpDecorate %45 DescriptorSet 0
  2231. OpDecorate %45 Binding 0
  2232. OpDecorate %49 Location 0
  2233. %2 = OpTypeVoid
  2234. %3 = OpTypeFunction %2
  2235. %6 = OpTypeBool
  2236. %7 = OpTypePointer Function %6
  2237. %9 = OpTypeFloat 32
  2238. %10 = OpTypeVector %9 4
  2239. %11 = OpTypePointer Input %10
  2240. %12 = OpVariable %11 Input
  2241. %13 = OpTypeInt 32 0
  2242. %14 = OpConstant %13 1
  2243. %15 = OpTypePointer Input %9
  2244. %18 = OpConstant %9 8.5
  2245. %21 = OpConstant %9 0.100000001
  2246. %25 = OpConstant %13 0
  2247. %28 = OpConstant %9 3.5
  2248. %30 = OpConstant %9 6
  2249. %36 = OpConstant %13 7
  2250. %40 = OpTypePointer Output %10
  2251. %41 = OpVariable %40 Output
  2252. %42 = OpTypeImage %9 2D 0 0 0 1 Unknown
  2253. %43 = OpTypeSampledImage %42
  2254. %44 = OpTypePointer UniformConstant %43
  2255. %45 = OpVariable %44 UniformConstant
  2256. %47 = OpTypeVector %9 2
  2257. %48 = OpTypePointer Input %47
  2258. %49 = OpVariable %48 Input
  2259. %53 = OpConstant %9 0.899999976
  2260. %54 = OpConstant %9 0.200000003
  2261. %55 = OpConstant %9 1
  2262. %56 = OpConstantComposite %10 %53 %54 %54 %55
  2263. %4 = OpFunction %2 None %3
  2264. %5 = OpLabel
  2265. %8 = OpVariable %7 Function
  2266. %16 = OpAccessChain %15 %12 %14
  2267. %17 = OpLoad %9 %16
  2268. %19 = OpFSub %9 %17 %18
  2269. %20 = OpExtInst %9 %1 FAbs %19
  2270. %22 = OpFOrdLessThan %6 %20 %21
  2271. OpSelectionMerge %24 None
  2272. OpBranchConditional %22 %23 %24
  2273. %23 = OpLabel
  2274. %26 = OpAccessChain %15 %12 %25
  2275. %27 = OpLoad %9 %26
  2276. %29 = OpFSub %9 %27 %28
  2277. %31 = OpFMod %9 %29 %30
  2278. %33 = OpFOrdLessThan %6 %31 %21
  2279. OpBranch %24
  2280. %24 = OpLabel
  2281. %34 = OpPhi %6 %22 %5 %33 %23
  2282. OpStore %8 %34
  2283. %35 = OpLoad %6 %8
  2284. %37 = OpGroupNonUniformAny %6 %36 %35
  2285. OpSelectionMerge %39 None
  2286. OpBranchConditional %37 %38 %52
  2287. %38 = OpLabel
  2288. %46 = OpLoad %43 %45
  2289. %50 = OpLoad %47 %49
  2290. %51 = OpImageSampleImplicitLod %10 %46 %50
  2291. OpStore %41 %51
  2292. OpBranch %39
  2293. %52 = OpLabel
  2294. OpStore %41 %56
  2295. OpBranch %39
  2296. %39 = OpLabel
  2297. OpReturn
  2298. OpFunctionEnd
  2299. )";
  2300. CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
  2301. EXPECT_THAT(SPV_ERROR_INVALID_DATA,
  2302. ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  2303. EXPECT_THAT(
  2304. getDiagnosticString(),
  2305. HasSubstr(
  2306. "Execution mode can only be used with the Fragment execution model"));
  2307. }
  2308. const std::string kNodeShaderPrelude = R"(
  2309. OpCapability Shader
  2310. OpCapability ShaderEnqueueAMDX
  2311. OpExtension "SPV_AMDX_shader_enqueue"
  2312. OpMemoryModel Logical GLSL450
  2313. OpEntryPoint GLCompute %main "main"
  2314. OpEntryPoint GLCompute %other "other"
  2315. )";
  2316. const std::string kNodeShaderPostlude = R"(
  2317. %uint = OpTypeInt 32 0
  2318. %uint_0 = OpConstant %uint 0
  2319. %uint_1 = OpConstant %uint 1
  2320. %node0 = OpConstantStringAMDX "node0"
  2321. %node1 = OpConstantStringAMDX "node1"
  2322. %node2 = OpConstantStringAMDX "node2"
  2323. %S = OpTypeStruct
  2324. %_payloadarr_S = OpTypeNodePayloadArrayAMDX %S
  2325. %_payloadarr_S_0 = OpTypeNodePayloadArrayAMDX %S
  2326. %bool = OpTypeBool
  2327. %true = OpConstantTrue %bool
  2328. %void = OpTypeVoid
  2329. %void_fn = OpTypeFunction %void
  2330. %main = OpFunction %void None %void_fn
  2331. %entry = OpLabel
  2332. OpReturn
  2333. OpFunctionEnd
  2334. %other = OpFunction %void None %void_fn
  2335. %entry0 = OpLabel
  2336. OpReturn
  2337. OpFunctionEnd
  2338. )";
  2339. TEST_F(ValidateMode, NodeShader) {
  2340. const std::string spirv = kNodeShaderPrelude + R"(
  2341. OpExecutionModeId %main ShaderIndexAMDX %uint_0
  2342. OpExecutionModeId %main IsApiEntryAMDX %true
  2343. OpExecutionModeId %main MaxNodeRecursionAMDX %uint_1
  2344. OpExecutionModeId %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2345. OpExecutionModeId %main SharesInputWithAMDX %node0 %uint_0
  2346. OpExecutionModeId %other ShaderIndexAMDX %uint_0
  2347. OpExecutionModeId %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2348. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2349. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2350. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2351. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2352. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2353. )" + kNodeShaderPostlude;
  2354. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2355. CompileSuccessfully(spirv, env);
  2356. EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
  2357. }
  2358. TEST_F(ValidateMode, NodeShaderModeShaderIndex) {
  2359. const std::string spirv = kNodeShaderPrelude + R"(
  2360. OpExecutionMode %main ShaderIndexAMDX %uint_0
  2361. OpExecutionModeId %main IsApiEntryAMDX %true
  2362. OpExecutionModeId %main MaxNodeRecursionAMDX %uint_1
  2363. OpExecutionModeId %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2364. OpExecutionModeId %main SharesInputWithAMDX %node0 %uint_0
  2365. OpExecutionMode %other ShaderIndexAMDX %uint_0
  2366. OpExecutionModeId %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2367. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2368. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2369. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2370. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2371. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2372. )" + kNodeShaderPostlude;
  2373. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2374. CompileSuccessfully(spirv, env);
  2375. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  2376. EXPECT_THAT(
  2377. getDiagnosticString(),
  2378. HasSubstr("OpExecutionMode is only valid when the Mode operand is an "
  2379. "execution mode that takes no Extra Operands, or takes Extra "
  2380. "Operands that are not id operands"));
  2381. }
  2382. TEST_F(ValidateMode, NodeShaderModeIsApiEntry) {
  2383. const std::string spirv = kNodeShaderPrelude + R"(
  2384. OpExecutionModeId %main ShaderIndexAMDX %uint_0
  2385. OpExecutionMode %main IsApiEntryAMDX %true
  2386. OpExecutionModeId %main MaxNodeRecursionAMDX %uint_1
  2387. OpExecutionModeId %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2388. OpExecutionModeId %main SharesInputWithAMDX %node0 %uint_0
  2389. OpExecutionModeId %other ShaderIndexAMDX %uint_0
  2390. OpExecutionModeId %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2391. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2392. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2393. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2394. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2395. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2396. )" + kNodeShaderPostlude;
  2397. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2398. CompileSuccessfully(spirv, env);
  2399. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  2400. EXPECT_THAT(
  2401. getDiagnosticString(),
  2402. HasSubstr("OpExecutionMode is only valid when the Mode operand is an "
  2403. "execution mode that takes no Extra Operands, or takes Extra "
  2404. "Operands that are not id operands"));
  2405. }
  2406. TEST_F(ValidateMode, NodeShaderModeMaxNodeRecursion) {
  2407. const std::string spirv = kNodeShaderPrelude + R"(
  2408. OpExecutionModeId %main ShaderIndexAMDX %uint_0
  2409. OpExecutionModeId %main IsApiEntryAMDX %true
  2410. OpExecutionMode %main MaxNodeRecursionAMDX %uint_1
  2411. OpExecutionModeId %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2412. OpExecutionModeId %main SharesInputWithAMDX %node0 %uint_0
  2413. OpExecutionModeId %other ShaderIndexAMDX %uint_0
  2414. OpExecutionModeId %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2415. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2416. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2417. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2418. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2419. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2420. )" + kNodeShaderPostlude;
  2421. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2422. CompileSuccessfully(spirv, env);
  2423. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  2424. EXPECT_THAT(
  2425. getDiagnosticString(),
  2426. HasSubstr("OpExecutionMode is only valid when the Mode operand is an "
  2427. "execution mode that takes no Extra Operands, or takes Extra "
  2428. "Operands that are not id operands"));
  2429. }
  2430. TEST_F(ValidateMode, NodeShaderModeMaxNumWorkgroups) {
  2431. const std::string spirv = kNodeShaderPrelude + R"(
  2432. OpExecutionModeId %main ShaderIndexAMDX %uint_0
  2433. OpExecutionModeId %main IsApiEntryAMDX %true
  2434. OpExecutionModeId %main MaxNodeRecursionAMDX %uint_1
  2435. OpExecutionMode %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2436. OpExecutionModeId %main SharesInputWithAMDX %node0 %uint_0
  2437. OpExecutionModeId %other ShaderIndexAMDX %uint_0
  2438. OpExecutionModeId %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2439. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2440. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2441. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2442. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2443. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2444. )" + kNodeShaderPostlude;
  2445. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2446. CompileSuccessfully(spirv, env);
  2447. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  2448. EXPECT_THAT(
  2449. getDiagnosticString(),
  2450. HasSubstr("OpExecutionMode is only valid when the Mode operand is an "
  2451. "execution mode that takes no Extra Operands, or takes Extra "
  2452. "Operands that are not id operands"));
  2453. }
  2454. TEST_F(ValidateMode, NodeShaderModeStaticNumWorkgroups) {
  2455. const std::string spirv = kNodeShaderPrelude + R"(
  2456. OpExecutionModeId %main ShaderIndexAMDX %uint_0
  2457. OpExecutionModeId %main IsApiEntryAMDX %true
  2458. OpExecutionModeId %main MaxNodeRecursionAMDX %uint_1
  2459. OpExecutionModeId %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2460. OpExecutionModeId %main SharesInputWithAMDX %node0 %uint_0
  2461. OpExecutionModeId %other ShaderIndexAMDX %uint_0
  2462. OpExecutionMode %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2463. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2464. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2465. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2466. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2467. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2468. )" + kNodeShaderPostlude;
  2469. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2470. CompileSuccessfully(spirv, env);
  2471. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  2472. EXPECT_THAT(
  2473. getDiagnosticString(),
  2474. HasSubstr("OpExecutionMode is only valid when the Mode operand is an "
  2475. "execution mode that takes no Extra Operands, or takes Extra "
  2476. "Operands that are not id operands"));
  2477. }
  2478. TEST_F(ValidateMode, NodeShaderModeSharesInputWith) {
  2479. const std::string spirv = kNodeShaderPrelude + R"(
  2480. OpExecutionModeId %main ShaderIndexAMDX %uint_0
  2481. OpExecutionModeId %main IsApiEntryAMDX %true
  2482. OpExecutionModeId %main MaxNodeRecursionAMDX %uint_1
  2483. OpExecutionModeId %main MaxNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2484. OpExecutionMode %main SharesInputWithAMDX %node0 %uint_0
  2485. OpExecutionModeId %other ShaderIndexAMDX %uint_0
  2486. OpExecutionModeId %other StaticNumWorkgroupsAMDX %uint_1 %uint_1 %uint_1
  2487. OpDecorateId %_payloadarr_S PayloadNodeNameAMDX %node1
  2488. OpDecorateId %_payloadarr_S_0 PayloadNodeNameAMDX %node2
  2489. OpDecorateId %_payloadarr_S PayloadNodeBaseIndexAMDX %uint_0
  2490. OpDecorateId %_payloadarr_S PayloadNodeArraySizeAMDX %uint_1
  2491. OpDecorateId %_payloadarr_S NodeSharesPayloadLimitsWithAMDX %_payloadarr_S_0
  2492. )" + kNodeShaderPostlude;
  2493. spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
  2494. CompileSuccessfully(spirv, env);
  2495. EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
  2496. EXPECT_THAT(
  2497. getDiagnosticString(),
  2498. HasSubstr("OpExecutionMode is only valid when the Mode operand is an "
  2499. "execution mode that takes no Extra Operands, or takes Extra "
  2500. "Operands that are not id operands"));
  2501. }
  2502. } // namespace
  2503. } // namespace val
  2504. } // namespace spvtools