val_interfaces_test.cpp 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543
  1. // Copyright (c) 2018 Google LLC.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string>
  15. #include "gmock/gmock.h"
  16. #include "test/unit_spirv.h"
  17. #include "test/val/val_fixtures.h"
  18. namespace spvtools {
  19. namespace val {
  20. namespace {
  21. using ::testing::HasSubstr;
  22. using ValidateInterfacesTest = spvtest::ValidateBase<bool>;
  23. TEST_F(ValidateInterfacesTest, EntryPointMissingInput) {
  24. std::string text = R"(
  25. OpCapability Shader
  26. OpMemoryModel Logical GLSL450
  27. OpEntryPoint Fragment %1 "func"
  28. OpExecutionMode %1 OriginUpperLeft
  29. %2 = OpTypeVoid
  30. %3 = OpTypeInt 32 0
  31. %4 = OpTypePointer Input %3
  32. %5 = OpVariable %4 Input
  33. %6 = OpTypeFunction %2
  34. %1 = OpFunction %2 None %6
  35. %7 = OpLabel
  36. %8 = OpLoad %3 %5
  37. OpReturn
  38. OpFunctionEnd
  39. )";
  40. CompileSuccessfully(text);
  41. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  42. EXPECT_THAT(
  43. getDiagnosticString(),
  44. HasSubstr(
  45. "Interface variable id <5> is used by entry point 'func' id <1>, "
  46. "but is not listed as an interface"));
  47. }
  48. TEST_F(ValidateInterfacesTest, EntryPointMissingOutput) {
  49. std::string text = R"(
  50. OpCapability Shader
  51. OpMemoryModel Logical GLSL450
  52. OpEntryPoint Fragment %1 "func"
  53. OpExecutionMode %1 OriginUpperLeft
  54. %2 = OpTypeVoid
  55. %3 = OpTypeInt 32 0
  56. %4 = OpTypePointer Output %3
  57. %5 = OpVariable %4 Output
  58. %6 = OpTypeFunction %2
  59. %1 = OpFunction %2 None %6
  60. %7 = OpLabel
  61. %8 = OpLoad %3 %5
  62. OpReturn
  63. OpFunctionEnd
  64. )";
  65. CompileSuccessfully(text);
  66. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  67. EXPECT_THAT(
  68. getDiagnosticString(),
  69. HasSubstr(
  70. "Interface variable id <5> is used by entry point 'func' id <1>, "
  71. "but is not listed as an interface"));
  72. }
  73. TEST_F(ValidateInterfacesTest, InterfaceMissingUseInSubfunction) {
  74. std::string text = R"(
  75. OpCapability Shader
  76. OpMemoryModel Logical GLSL450
  77. OpEntryPoint Fragment %1 "func"
  78. OpExecutionMode %1 OriginUpperLeft
  79. %2 = OpTypeVoid
  80. %3 = OpTypeInt 32 0
  81. %4 = OpTypePointer Input %3
  82. %5 = OpVariable %4 Input
  83. %6 = OpTypeFunction %2
  84. %1 = OpFunction %2 None %6
  85. %7 = OpLabel
  86. %8 = OpFunctionCall %2 %9
  87. OpReturn
  88. OpFunctionEnd
  89. %9 = OpFunction %2 None %6
  90. %10 = OpLabel
  91. %11 = OpLoad %3 %5
  92. OpReturn
  93. OpFunctionEnd
  94. )";
  95. CompileSuccessfully(text);
  96. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  97. EXPECT_THAT(
  98. getDiagnosticString(),
  99. HasSubstr(
  100. "Interface variable id <5> is used by entry point 'func' id <1>, "
  101. "but is not listed as an interface"));
  102. }
  103. TEST_F(ValidateInterfacesTest, TwoEntryPointsOneFunction) {
  104. std::string text = R"(
  105. OpCapability Shader
  106. OpMemoryModel Logical GLSL450
  107. OpEntryPoint Fragment %1 "func" %2
  108. OpEntryPoint Fragment %1 "func2"
  109. OpExecutionMode %1 OriginUpperLeft
  110. %3 = OpTypeVoid
  111. %4 = OpTypeInt 32 0
  112. %5 = OpTypePointer Input %4
  113. %2 = OpVariable %5 Input
  114. %6 = OpTypeFunction %3
  115. %1 = OpFunction %3 None %6
  116. %7 = OpLabel
  117. %8 = OpLoad %4 %2
  118. OpReturn
  119. OpFunctionEnd
  120. )";
  121. CompileSuccessfully(text);
  122. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
  123. EXPECT_THAT(
  124. getDiagnosticString(),
  125. HasSubstr(
  126. "Interface variable id <2> is used by entry point 'func2' id <1>, "
  127. "but is not listed as an interface"));
  128. }
  129. TEST_F(ValidateInterfacesTest, MissingInterfaceThroughInitializer) {
  130. const std::string text = R"(
  131. OpCapability Shader
  132. OpCapability VariablePointers
  133. OpMemoryModel Logical GLSL450
  134. OpEntryPoint Fragment %1 "func"
  135. OpExecutionMode %1 OriginUpperLeft
  136. %2 = OpTypeVoid
  137. %3 = OpTypeInt 32 0
  138. %4 = OpTypePointer Input %3
  139. %5 = OpTypePointer Function %4
  140. %6 = OpVariable %4 Input
  141. %7 = OpTypeFunction %2
  142. %1 = OpFunction %2 None %7
  143. %8 = OpLabel
  144. %9 = OpVariable %5 Function %6
  145. OpReturn
  146. OpFunctionEnd
  147. )";
  148. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  149. ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  150. EXPECT_THAT(
  151. getDiagnosticString(),
  152. HasSubstr(
  153. "Interface variable id <6> is used by entry point 'func' id <1>, "
  154. "but is not listed as an interface"));
  155. }
  156. TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p3) {
  157. const std::string text = R"(
  158. OpCapability Shader
  159. OpMemoryModel Logical GLSL450
  160. OpEntryPoint GLCompute %main "main" %var %var
  161. OpExecutionMode %main LocalSize 1 1 1
  162. %void = OpTypeVoid
  163. %uint = OpTypeInt 32 0
  164. %uint3 = OpTypeVector %uint 3
  165. %struct = OpTypeStruct %uint3
  166. %ptr_struct = OpTypePointer Input %struct
  167. %var = OpVariable %ptr_struct Input
  168. %func_ty = OpTypeFunction %void
  169. %main = OpFunction %void None %func_ty
  170. %1 = OpLabel
  171. OpReturn
  172. OpFunctionEnd
  173. )";
  174. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  175. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  176. }
  177. TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p4) {
  178. const std::string text = R"(
  179. OpCapability Shader
  180. OpMemoryModel Logical GLSL450
  181. OpEntryPoint GLCompute %main "main" %var %var
  182. OpExecutionMode %main LocalSize 1 1 1
  183. OpName %main "main"
  184. OpName %var "var"
  185. %void = OpTypeVoid
  186. %uint = OpTypeInt 32 0
  187. %uint3 = OpTypeVector %uint 3
  188. %struct = OpTypeStruct %uint3
  189. %ptr_struct = OpTypePointer Input %struct
  190. %var = OpVariable %ptr_struct Input
  191. %func_ty = OpTypeFunction %void
  192. %main = OpFunction %void None %func_ty
  193. %1 = OpLabel
  194. OpReturn
  195. OpFunctionEnd
  196. )";
  197. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
  198. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  199. EXPECT_THAT(
  200. getDiagnosticString(),
  201. HasSubstr("Non-unique OpEntryPoint interface '2[%var]' is disallowed"));
  202. }
  203. TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p3) {
  204. const std::string text = R"(
  205. OpCapability Shader
  206. OpMemoryModel Logical GLSL450
  207. OpEntryPoint GLCompute %main "main"
  208. OpExecutionMode %main LocalSize 1 1 1
  209. %void = OpTypeVoid
  210. %uint = OpTypeInt 32 0
  211. %uint3 = OpTypeVector %uint 3
  212. %struct = OpTypeStruct %uint3
  213. %ptr_struct = OpTypePointer StorageBuffer %struct
  214. %var = OpVariable %ptr_struct StorageBuffer
  215. %func_ty = OpTypeFunction %void
  216. %main = OpFunction %void None %func_ty
  217. %1 = OpLabel
  218. %ld = OpLoad %struct %var
  219. OpReturn
  220. OpFunctionEnd
  221. )";
  222. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  223. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  224. }
  225. TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p4) {
  226. const std::string text = R"(
  227. OpCapability Shader
  228. OpMemoryModel Logical GLSL450
  229. OpEntryPoint GLCompute %main "main"
  230. OpExecutionMode %main LocalSize 1 1 1
  231. OpName %var "var"
  232. %void = OpTypeVoid
  233. %uint = OpTypeInt 32 0
  234. %uint3 = OpTypeVector %uint 3
  235. %struct = OpTypeStruct %uint3
  236. %ptr_struct = OpTypePointer StorageBuffer %struct
  237. %var = OpVariable %ptr_struct StorageBuffer
  238. %func_ty = OpTypeFunction %void
  239. %main = OpFunction %void None %func_ty
  240. %1 = OpLabel
  241. %ld = OpLoad %struct %var
  242. OpReturn
  243. OpFunctionEnd
  244. )";
  245. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
  246. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  247. EXPECT_THAT(getDiagnosticString(),
  248. HasSubstr("Interface variable id <2> is used by entry point "
  249. "'main' id <1>, but is not listed as an interface"));
  250. }
  251. TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p3) {
  252. const std::string text = R"(
  253. OpCapability Shader
  254. OpMemoryModel Logical GLSL450
  255. OpEntryPoint GLCompute %main "main" %var
  256. OpExecutionMode %main LocalSize 1 1 1
  257. OpName %var "var"
  258. %void = OpTypeVoid
  259. %uint = OpTypeInt 32 0
  260. %uint3 = OpTypeVector %uint 3
  261. %struct = OpTypeStruct %uint3
  262. %ptr_struct = OpTypePointer Function %struct
  263. %func_ty = OpTypeFunction %void
  264. %main = OpFunction %void None %func_ty
  265. %1 = OpLabel
  266. %var = OpVariable %ptr_struct Function
  267. OpReturn
  268. OpFunctionEnd
  269. )";
  270. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  271. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
  272. EXPECT_THAT(getDiagnosticString(),
  273. HasSubstr("OpEntryPoint interfaces must be OpVariables with "
  274. "Storage Class of Input(1) or Output(3). Found Storage "
  275. "Class 7 for Entry Point id 1."));
  276. }
  277. TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p4) {
  278. const std::string text = R"(
  279. OpCapability Shader
  280. OpMemoryModel Logical GLSL450
  281. OpEntryPoint GLCompute %main "main" %var
  282. OpExecutionMode %main LocalSize 1 1 1
  283. OpName %var "var"
  284. %void = OpTypeVoid
  285. %uint = OpTypeInt 32 0
  286. %uint3 = OpTypeVector %uint 3
  287. %struct = OpTypeStruct %uint3
  288. %ptr_struct = OpTypePointer Function %struct
  289. %func_ty = OpTypeFunction %void
  290. %main = OpFunction %void None %func_ty
  291. %1 = OpLabel
  292. %var = OpVariable %ptr_struct Function
  293. OpReturn
  294. OpFunctionEnd
  295. )";
  296. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
  297. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  298. EXPECT_THAT(
  299. getDiagnosticString(),
  300. HasSubstr("OpEntryPoint interfaces should only list global variables"));
  301. }
  302. TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_NotAllUsedGlobals) {
  303. const std::string text = R"(
  304. OpCapability Shader
  305. OpMemoryModel Logical GLSL450
  306. OpEntryPoint GLCompute %main "main"
  307. OpExecutionMode %main LocalSize 1 1 1
  308. OpName %var "var"
  309. %void = OpTypeVoid
  310. %uint = OpTypeInt 32 0
  311. %uint3 = OpTypeVector %uint 3
  312. %struct = OpTypeStruct %uint3
  313. %ptr_struct = OpTypePointer StorageBuffer %struct
  314. %var = OpVariable %ptr_struct StorageBuffer
  315. %func_ty = OpTypeFunction %void
  316. %main = OpFunction %void None %func_ty
  317. %1 = OpLabel
  318. %ld = OpLoad %struct %var
  319. OpReturn
  320. OpFunctionEnd
  321. )";
  322. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  323. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  324. }
  325. TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_DuplicateInterface) {
  326. const std::string text = R"(
  327. OpCapability Shader
  328. OpMemoryModel Logical GLSL450
  329. OpEntryPoint GLCompute %main "main" %gid %gid
  330. OpExecutionMode %main LocalSize 1 1 1
  331. OpDecorate %gid BuiltIn GlobalInvocationId
  332. %void = OpTypeVoid
  333. %int = OpTypeInt 32 0
  334. %int3 = OpTypeVector %int 3
  335. %ptr_input_int3 = OpTypePointer Input %int3
  336. %gid = OpVariable %ptr_input_int3 Input
  337. %void_fn = OpTypeFunction %void
  338. %main = OpFunction %void None %void_fn
  339. %entry = OpLabel
  340. OpReturn
  341. OpFunctionEnd
  342. )";
  343. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
  344. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  345. }
  346. TEST_F(ValidateInterfacesTest, SPV14MultipleEntryPointsSameFunction) {
  347. const std::string text = R"(
  348. OpCapability Shader
  349. OpMemoryModel Logical GLSL450
  350. OpEntryPoint GLCompute %main "main1" %gid
  351. OpEntryPoint GLCompute %main "main2" %gid
  352. OpExecutionMode %main LocalSize 1 1 1
  353. OpDecorate %gid BuiltIn GlobalInvocationId
  354. %void = OpTypeVoid
  355. %int = OpTypeInt 32 0
  356. %int3 = OpTypeVector %int 3
  357. %ptr_input_int3 = OpTypePointer Input %int3
  358. %gid = OpVariable %ptr_input_int3 Input
  359. %void_fn = OpTypeFunction %void
  360. %main = OpFunction %void None %void_fn
  361. %entry = OpLabel
  362. OpReturn
  363. OpFunctionEnd
  364. )";
  365. CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
  366. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
  367. }
  368. TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentVariable) {
  369. const std::string text = R"(
  370. OpCapability Shader
  371. OpMemoryModel Logical GLSL450
  372. OpEntryPoint Fragment %main "main" %var
  373. OpExecutionMode %main OriginUpperLeft
  374. OpDecorate %var Location 0
  375. OpDecorate %var Location 1
  376. %void = OpTypeVoid
  377. %void_fn = OpTypeFunction %void
  378. %float = OpTypeFloat 32
  379. %ptr_input_float = OpTypePointer Input %float
  380. %var = OpVariable %ptr_input_float Input
  381. %main = OpFunction %void None %void_fn
  382. %entry = OpLabel
  383. OpReturn
  384. OpFunctionEnd
  385. )";
  386. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  387. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  388. EXPECT_THAT(getDiagnosticString(),
  389. HasSubstr("Variable has conflicting location decorations"));
  390. }
  391. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableAndMemberAssigned) {
  392. const std::string text = R"(
  393. OpCapability Shader
  394. OpMemoryModel Logical GLSL450
  395. OpEntryPoint Fragment %main "main" %var
  396. OpExecutionMode %main OriginUpperLeft
  397. OpDecorate %var Location 0
  398. OpDecorate %struct Block
  399. OpMemberDecorate %struct 0 Location 0
  400. %void = OpTypeVoid
  401. %void_fn = OpTypeFunction %void
  402. %float = OpTypeFloat 32
  403. %struct = OpTypeStruct %float
  404. %ptr_input_struct = OpTypePointer Input %struct
  405. %var = OpVariable %ptr_input_struct Input
  406. %main = OpFunction %void None %void_fn
  407. %entry = OpLabel
  408. OpReturn
  409. OpFunctionEnd
  410. )";
  411. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  412. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  413. EXPECT_THAT(getDiagnosticString(),
  414. AnyVUID("VUID-StandaloneSpirv-Location-04918"));
  415. EXPECT_THAT(getDiagnosticString(),
  416. HasSubstr("Members cannot be assigned a location"));
  417. }
  418. TEST_F(ValidateInterfacesTest, VulkanLocationsMemberAndSubMemberAssigned) {
  419. const std::string text = R"(
  420. OpCapability Shader
  421. OpMemoryModel Logical GLSL450
  422. OpEntryPoint Fragment %main "main" %var
  423. OpExecutionMode %main OriginUpperLeft
  424. OpDecorate %outer Block
  425. OpMemberDecorate %outer 0 Location 0
  426. OpMemberDecorate %struct 0 Location 0
  427. %void = OpTypeVoid
  428. %void_fn = OpTypeFunction %void
  429. %float = OpTypeFloat 32
  430. %struct = OpTypeStruct %float
  431. %outer = OpTypeStruct %struct
  432. %ptr_input_outer = OpTypePointer Input %outer
  433. %var = OpVariable %ptr_input_outer Input
  434. %main = OpFunction %void None %void_fn
  435. %entry = OpLabel
  436. OpReturn
  437. OpFunctionEnd
  438. )";
  439. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  440. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  441. EXPECT_THAT(getDiagnosticString(),
  442. AnyVUID("VUID-StandaloneSpirv-Location-04918"));
  443. EXPECT_THAT(getDiagnosticString(),
  444. HasSubstr("Members cannot be assigned a location"));
  445. }
  446. TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentStructMember) {
  447. const std::string text = R"(
  448. OpCapability Shader
  449. OpMemoryModel Logical GLSL450
  450. OpEntryPoint Fragment %main "main" %var
  451. OpExecutionMode %main OriginUpperLeft
  452. OpDecorate %struct Block
  453. OpMemberDecorate %struct 1 Location 0
  454. OpMemberDecorate %struct 1 Location 1
  455. %void = OpTypeVoid
  456. %void_fn = OpTypeFunction %void
  457. %float = OpTypeFloat 32
  458. %struct = OpTypeStruct %float %float
  459. %ptr_input_struct = OpTypePointer Input %struct
  460. %var = OpVariable %ptr_input_struct Input
  461. %main = OpFunction %void None %void_fn
  462. %entry = OpLabel
  463. OpReturn
  464. OpFunctionEnd
  465. )";
  466. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  467. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  468. EXPECT_THAT(getDiagnosticString(),
  469. HasSubstr("Member index 1 has conflicting location assignments"));
  470. }
  471. TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
  472. const std::string text = R"(
  473. OpCapability Shader
  474. OpMemoryModel Logical GLSL450
  475. OpEntryPoint Fragment %main "main" %var
  476. OpExecutionMode %main OriginUpperLeft
  477. OpDecorate %struct Block
  478. OpMemberDecorate %struct 1 Location 1
  479. %void = OpTypeVoid
  480. %void_fn = OpTypeFunction %void
  481. %float = OpTypeFloat 32
  482. %struct = OpTypeStruct %float %float
  483. %ptr_input_struct = OpTypePointer Input %struct
  484. %var = OpVariable %ptr_input_struct Input
  485. %main = OpFunction %void None %void_fn
  486. %entry = OpLabel
  487. OpReturn
  488. OpFunctionEnd
  489. )";
  490. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  491. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  492. EXPECT_THAT(getDiagnosticString(),
  493. HasSubstr("Member index 0 is missing a location assignment"));
  494. }
  495. TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentNonBlockStruct) {
  496. const std::string text = R"(
  497. OpCapability Shader
  498. OpMemoryModel Logical GLSL450
  499. OpEntryPoint Fragment %main "main" %var
  500. OpExecutionMode %main OriginUpperLeft
  501. %void = OpTypeVoid
  502. %void_fn = OpTypeFunction %void
  503. %float = OpTypeFloat 32
  504. %struct = OpTypeStruct %float %float
  505. %ptr_input_struct = OpTypePointer Input %struct
  506. %var = OpVariable %ptr_input_struct Input
  507. %main = OpFunction %void None %void_fn
  508. %entry = OpLabel
  509. OpReturn
  510. OpFunctionEnd
  511. )";
  512. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  513. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  514. EXPECT_THAT(getDiagnosticString(),
  515. HasSubstr("Variable must be decorated with a location"));
  516. }
  517. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictInput) {
  518. const std::string text = R"(
  519. OpCapability Shader
  520. OpMemoryModel Logical GLSL450
  521. OpEntryPoint Fragment %main "main" %var1 %var2
  522. OpExecutionMode %main OriginUpperLeft
  523. OpDecorate %var1 Location 0
  524. OpDecorate %var2 Location 0
  525. %void = OpTypeVoid
  526. %void_fn = OpTypeFunction %void
  527. %float = OpTypeFloat 32
  528. %struct = OpTypeStruct %float %float
  529. %ptr_input_struct = OpTypePointer Input %struct
  530. %var1 = OpVariable %ptr_input_struct Input
  531. %var2 = OpVariable %ptr_input_struct Input
  532. %main = OpFunction %void None %void_fn
  533. %entry = OpLabel
  534. OpReturn
  535. OpFunctionEnd
  536. )";
  537. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  538. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  539. EXPECT_THAT(getDiagnosticString(),
  540. HasSubstr("Entry-point has conflicting input location assignment "
  541. "at location 0"));
  542. }
  543. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutput) {
  544. const std::string text = R"(
  545. OpCapability Shader
  546. OpMemoryModel Logical GLSL450
  547. OpEntryPoint Fragment %main "main" %var1 %var2
  548. OpExecutionMode %main OriginUpperLeft
  549. OpDecorate %var1 Location 1
  550. OpDecorate %var2 Location 1
  551. %void = OpTypeVoid
  552. %void_fn = OpTypeFunction %void
  553. %float = OpTypeFloat 32
  554. %struct = OpTypeStruct %float %float
  555. %ptr_output_struct = OpTypePointer Output %struct
  556. %var1 = OpVariable %ptr_output_struct Output
  557. %var2 = OpVariable %ptr_output_struct Output
  558. %main = OpFunction %void None %void_fn
  559. %entry = OpLabel
  560. OpReturn
  561. OpFunctionEnd
  562. )";
  563. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  564. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  565. EXPECT_THAT(
  566. getDiagnosticString(),
  567. HasSubstr("Entry-point has conflicting output location assignment "
  568. "at location 1"));
  569. }
  570. TEST_F(ValidateInterfacesTest,
  571. VulkanLocationsSameLocationInputAndOutputNoConflict) {
  572. const std::string text = R"(
  573. OpCapability Shader
  574. OpMemoryModel Logical GLSL450
  575. OpEntryPoint Fragment %main "main" %var1 %var2
  576. OpExecutionMode %main OriginUpperLeft
  577. OpDecorate %var1 Location 1
  578. OpDecorate %var2 Location 1
  579. %void = OpTypeVoid
  580. %void_fn = OpTypeFunction %void
  581. %float = OpTypeFloat 32
  582. %struct = OpTypeStruct %float %float
  583. %ptr_input_struct = OpTypePointer Input %struct
  584. %ptr_output_struct = OpTypePointer Output %struct
  585. %var1 = OpVariable %ptr_input_struct Input
  586. %var2 = OpVariable %ptr_output_struct Output
  587. %main = OpFunction %void None %void_fn
  588. %entry = OpLabel
  589. OpReturn
  590. OpFunctionEnd
  591. )";
  592. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  593. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  594. }
  595. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableInGap) {
  596. const std::string text = R"(
  597. OpCapability Shader
  598. OpMemoryModel Logical GLSL450
  599. OpEntryPoint Fragment %main "main" %var1 %var2
  600. OpExecutionMode %main OriginUpperLeft
  601. OpDecorate %struct Block
  602. OpMemberDecorate %struct 0 Location 0
  603. OpMemberDecorate %struct 1 Location 2
  604. OpDecorate %var2 Location 1
  605. %void = OpTypeVoid
  606. %void_fn = OpTypeFunction %void
  607. %float = OpTypeFloat 32
  608. %struct = OpTypeStruct %float %float
  609. %ptr_input_struct = OpTypePointer Input %struct
  610. %ptr_input_float = OpTypePointer Input %float
  611. %var1 = OpVariable %ptr_input_struct Input
  612. %var2 = OpVariable %ptr_input_float Input
  613. %main = OpFunction %void None %void_fn
  614. %entry = OpLabel
  615. OpReturn
  616. OpFunctionEnd
  617. )";
  618. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  619. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  620. }
  621. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeFloatVectorConflict) {
  622. const std::string text = R"(
  623. OpCapability Shader
  624. OpCapability Float64
  625. OpMemoryModel Logical GLSL450
  626. OpEntryPoint Fragment %main "main" %var1 %var2
  627. OpExecutionMode %main OriginUpperLeft
  628. OpDecorate %var1 Location 0
  629. OpDecorate %var2 Location 1
  630. %void = OpTypeVoid
  631. %void_fn = OpTypeFunction %void
  632. %float = OpTypeFloat 32
  633. %double = OpTypeFloat 64
  634. %vector = OpTypeVector %double 3
  635. %ptr_input_float = OpTypePointer Input %float
  636. %ptr_input_vector = OpTypePointer Input %vector
  637. %var1 = OpVariable %ptr_input_vector Input
  638. %var2 = OpVariable %ptr_input_float Input
  639. %main = OpFunction %void None %void_fn
  640. %entry = OpLabel
  641. OpReturn
  642. OpFunctionEnd
  643. )";
  644. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  645. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  646. EXPECT_THAT(getDiagnosticString(),
  647. HasSubstr("Entry-point has conflicting input location assignment "
  648. "at location 1"));
  649. }
  650. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeIntVectorConflict) {
  651. const std::string text = R"(
  652. OpCapability Shader
  653. OpCapability Int64
  654. OpMemoryModel Logical GLSL450
  655. OpEntryPoint Fragment %main "main" %var1 %var2
  656. OpExecutionMode %main OriginUpperLeft
  657. OpDecorate %var1 Location 0
  658. OpDecorate %var1 Flat
  659. OpDecorate %var2 Location 1
  660. OpDecorate %var2 Flat
  661. %void = OpTypeVoid
  662. %void_fn = OpTypeFunction %void
  663. %float = OpTypeFloat 32
  664. %long = OpTypeInt 64 0
  665. %vector = OpTypeVector %long 4
  666. %ptr_input_float = OpTypePointer Input %float
  667. %ptr_input_vector = OpTypePointer Input %vector
  668. %var1 = OpVariable %ptr_input_vector Input
  669. %var2 = OpVariable %ptr_input_float Input
  670. %main = OpFunction %void None %void_fn
  671. %entry = OpLabel
  672. OpReturn
  673. OpFunctionEnd
  674. )";
  675. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  676. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  677. EXPECT_THAT(getDiagnosticString(),
  678. HasSubstr("Entry-point has conflicting input location assignment "
  679. "at location 1"));
  680. }
  681. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix2x2Conflict) {
  682. const std::string text = R"(
  683. OpCapability Shader
  684. OpMemoryModel Logical GLSL450
  685. OpEntryPoint Fragment %main "main" %var1 %var2
  686. OpExecutionMode %main OriginUpperLeft
  687. OpDecorate %var1 Location 0
  688. OpDecorate %var2 Location 1
  689. %void = OpTypeVoid
  690. %void_fn = OpTypeFunction %void
  691. %float = OpTypeFloat 32
  692. %vector = OpTypeVector %float 2
  693. %matrix = OpTypeMatrix %vector 2
  694. %ptr_input_float = OpTypePointer Input %float
  695. %ptr_input_matrix = OpTypePointer Input %matrix
  696. %var1 = OpVariable %ptr_input_matrix Input
  697. %var2 = OpVariable %ptr_input_float Input
  698. %main = OpFunction %void None %void_fn
  699. %entry = OpLabel
  700. OpReturn
  701. OpFunctionEnd
  702. )";
  703. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  704. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  705. EXPECT_THAT(getDiagnosticString(),
  706. HasSubstr("Entry-point has conflicting input location assignment "
  707. "at location 1"));
  708. }
  709. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix3x3Conflict) {
  710. const std::string text = R"(
  711. OpCapability Shader
  712. OpMemoryModel Logical GLSL450
  713. OpEntryPoint Fragment %main "main" %var1 %var2
  714. OpExecutionMode %main OriginUpperLeft
  715. OpDecorate %var1 Location 0
  716. OpDecorate %var2 Location 2
  717. %void = OpTypeVoid
  718. %void_fn = OpTypeFunction %void
  719. %float = OpTypeFloat 32
  720. %vector = OpTypeVector %float 3
  721. %matrix = OpTypeMatrix %vector 3
  722. %ptr_input_float = OpTypePointer Input %float
  723. %ptr_input_matrix = OpTypePointer Input %matrix
  724. %var1 = OpVariable %ptr_input_matrix Input
  725. %var2 = OpVariable %ptr_input_float Input
  726. %main = OpFunction %void None %void_fn
  727. %entry = OpLabel
  728. OpReturn
  729. OpFunctionEnd
  730. )";
  731. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  732. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  733. EXPECT_THAT(getDiagnosticString(),
  734. HasSubstr("Entry-point has conflicting input location assignment "
  735. "at location 2"));
  736. }
  737. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Conflict) {
  738. const std::string text = R"(
  739. OpCapability Shader
  740. OpMemoryModel Logical GLSL450
  741. OpEntryPoint Fragment %main "main" %var1 %var2
  742. OpExecutionMode %main OriginUpperLeft
  743. OpDecorate %var1 Location 0
  744. OpDecorate %var2 Location 3
  745. %void = OpTypeVoid
  746. %void_fn = OpTypeFunction %void
  747. %float = OpTypeFloat 32
  748. %vector = OpTypeVector %float 4
  749. %matrix = OpTypeMatrix %vector 4
  750. %ptr_input_float = OpTypePointer Input %float
  751. %ptr_input_matrix = OpTypePointer Input %matrix
  752. %var1 = OpVariable %ptr_input_matrix Input
  753. %var2 = OpVariable %ptr_input_float Input
  754. %main = OpFunction %void None %void_fn
  755. %entry = OpLabel
  756. OpReturn
  757. OpFunctionEnd
  758. )";
  759. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  760. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  761. EXPECT_THAT(getDiagnosticString(),
  762. HasSubstr("Entry-point has conflicting input location assignment "
  763. "at location 3"));
  764. }
  765. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix2x2Conflict) {
  766. const std::string text = R"(
  767. OpCapability Shader
  768. OpCapability Float64
  769. OpMemoryModel Logical GLSL450
  770. OpEntryPoint Fragment %main "main" %var1 %var2
  771. OpExecutionMode %main OriginUpperLeft
  772. OpDecorate %var1 Location 0
  773. OpDecorate %var2 Location 1
  774. %void = OpTypeVoid
  775. %void_fn = OpTypeFunction %void
  776. %float = OpTypeFloat 32
  777. %double = OpTypeFloat 64
  778. %vector = OpTypeVector %double 2
  779. %matrix = OpTypeMatrix %vector 2
  780. %ptr_input_float = OpTypePointer Input %float
  781. %ptr_input_matrix = OpTypePointer Input %matrix
  782. %var1 = OpVariable %ptr_input_matrix Input
  783. %var2 = OpVariable %ptr_input_float Input
  784. %main = OpFunction %void None %void_fn
  785. %entry = OpLabel
  786. OpReturn
  787. OpFunctionEnd
  788. )";
  789. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  790. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  791. EXPECT_THAT(getDiagnosticString(),
  792. HasSubstr("Entry-point has conflicting input location assignment "
  793. "at location 1"));
  794. }
  795. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix3x3Conflict) {
  796. const std::string text = R"(
  797. OpCapability Shader
  798. OpCapability Float64
  799. OpMemoryModel Logical GLSL450
  800. OpEntryPoint Fragment %main "main" %var1 %var2
  801. OpExecutionMode %main OriginUpperLeft
  802. OpDecorate %var1 Location 0
  803. OpDecorate %var2 Location 5
  804. %void = OpTypeVoid
  805. %void_fn = OpTypeFunction %void
  806. %float = OpTypeFloat 32
  807. %double = OpTypeFloat 64
  808. %vector = OpTypeVector %double 3
  809. %matrix = OpTypeMatrix %vector 3
  810. %ptr_input_float = OpTypePointer Input %float
  811. %ptr_input_matrix = OpTypePointer Input %matrix
  812. %var1 = OpVariable %ptr_input_matrix Input
  813. %var2 = OpVariable %ptr_input_float Input
  814. %main = OpFunction %void None %void_fn
  815. %entry = OpLabel
  816. OpReturn
  817. OpFunctionEnd
  818. )";
  819. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  820. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  821. EXPECT_THAT(getDiagnosticString(),
  822. HasSubstr("Entry-point has conflicting input location assignment "
  823. "at location 5"));
  824. }
  825. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix4x4Conflict) {
  826. const std::string text = R"(
  827. OpCapability Shader
  828. OpCapability Float64
  829. OpMemoryModel Logical GLSL450
  830. OpEntryPoint Fragment %main "main" %var1 %var2
  831. OpExecutionMode %main OriginUpperLeft
  832. OpDecorate %var1 Location 0
  833. OpDecorate %var2 Location 7
  834. %void = OpTypeVoid
  835. %void_fn = OpTypeFunction %void
  836. %float = OpTypeFloat 32
  837. %double = OpTypeFloat 64
  838. %vector = OpTypeVector %double 4
  839. %matrix = OpTypeMatrix %vector 4
  840. %ptr_input_float = OpTypePointer Input %float
  841. %ptr_input_matrix = OpTypePointer Input %matrix
  842. %var1 = OpVariable %ptr_input_matrix Input
  843. %var2 = OpVariable %ptr_input_float Input
  844. %main = OpFunction %void None %void_fn
  845. %entry = OpLabel
  846. OpReturn
  847. OpFunctionEnd
  848. )";
  849. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  850. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  851. EXPECT_THAT(getDiagnosticString(),
  852. HasSubstr("Entry-point has conflicting input location assignment "
  853. "at location 7"));
  854. }
  855. TEST_F(ValidateInterfacesTest, VulkanLocationsArray2Conflict) {
  856. const std::string text = R"(
  857. OpCapability Shader
  858. OpMemoryModel Logical GLSL450
  859. OpEntryPoint Fragment %main "main" %var1 %var2
  860. OpExecutionMode %main OriginUpperLeft
  861. OpDecorate %var1 Location 0
  862. OpDecorate %var2 Location 1
  863. %void = OpTypeVoid
  864. %void_fn = OpTypeFunction %void
  865. %float = OpTypeFloat 32
  866. %int = OpTypeInt 32 0
  867. %int_2 = OpConstant %int 2
  868. %array = OpTypeArray %int %int_2
  869. %struct = OpTypeStruct %array
  870. %ptr_input_float = OpTypePointer Input %float
  871. %ptr_input_struct = OpTypePointer Input %struct
  872. %var1 = OpVariable %ptr_input_struct Input
  873. %var2 = OpVariable %ptr_input_float Input
  874. %main = OpFunction %void None %void_fn
  875. %entry = OpLabel
  876. OpReturn
  877. OpFunctionEnd
  878. )";
  879. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  880. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  881. EXPECT_THAT(getDiagnosticString(),
  882. HasSubstr("Entry-point has conflicting input location assignment "
  883. "at location 1"));
  884. }
  885. TEST_F(ValidateInterfacesTest, VulkanLocationsArray4Conflict) {
  886. const std::string text = R"(
  887. OpCapability Shader
  888. OpMemoryModel Logical GLSL450
  889. OpEntryPoint Fragment %main "main" %var1 %var2
  890. OpExecutionMode %main OriginUpperLeft
  891. OpDecorate %var1 Location 0
  892. OpDecorate %var2 Location 3
  893. %void = OpTypeVoid
  894. %void_fn = OpTypeFunction %void
  895. %float = OpTypeFloat 32
  896. %int = OpTypeInt 32 0
  897. %int_4 = OpConstant %int 4
  898. %array = OpTypeArray %int %int_4
  899. %struct = OpTypeStruct %array
  900. %ptr_input_float = OpTypePointer Input %float
  901. %ptr_input_struct = OpTypePointer Input %struct
  902. %var1 = OpVariable %ptr_input_struct Input
  903. %var2 = OpVariable %ptr_input_float Input
  904. %main = OpFunction %void None %void_fn
  905. %entry = OpLabel
  906. OpReturn
  907. OpFunctionEnd
  908. )";
  909. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  910. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  911. EXPECT_THAT(getDiagnosticString(),
  912. HasSubstr("Entry-point has conflicting input location assignment "
  913. "at location 3"));
  914. }
  915. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Array4Conflict) {
  916. const std::string text = R"(
  917. OpCapability Shader
  918. OpMemoryModel Logical GLSL450
  919. OpEntryPoint Fragment %main "main" %var1 %var2
  920. OpExecutionMode %main OriginUpperLeft
  921. OpDecorate %var1 Location 0
  922. OpDecorate %var2 Location 15
  923. %void = OpTypeVoid
  924. %void_fn = OpTypeFunction %void
  925. %float = OpTypeFloat 32
  926. %int = OpTypeInt 32 0
  927. %int_4 = OpConstant %int 4
  928. %vector = OpTypeVector %float 4
  929. %matrix = OpTypeMatrix %vector 4
  930. %array = OpTypeArray %matrix %int_4
  931. %struct = OpTypeStruct %array
  932. %ptr_input_float = OpTypePointer Input %float
  933. %ptr_input_struct = OpTypePointer Input %struct
  934. %var1 = OpVariable %ptr_input_struct Input
  935. %var2 = OpVariable %ptr_input_float Input
  936. %main = OpFunction %void None %void_fn
  937. %entry = OpLabel
  938. OpReturn
  939. OpFunctionEnd
  940. )";
  941. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  942. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  943. EXPECT_THAT(getDiagnosticString(),
  944. HasSubstr("Entry-point has conflicting input location assignment "
  945. "at location 15"));
  946. }
  947. TEST_F(ValidateInterfacesTest, VulkanLocationsComponentDisambiguates) {
  948. const std::string text = R"(
  949. OpCapability Shader
  950. OpMemoryModel Logical GLSL450
  951. OpEntryPoint Fragment %main "main" %var1
  952. OpExecutionMode %main OriginUpperLeft
  953. OpDecorate %struct Block
  954. OpMemberDecorate %struct 0 Location 0
  955. OpMemberDecorate %struct 0 Component 0
  956. OpMemberDecorate %struct 1 Location 0
  957. OpMemberDecorate %struct 1 Component 1
  958. %void = OpTypeVoid
  959. %void_fn = OpTypeFunction %void
  960. %float = OpTypeFloat 32
  961. %struct = OpTypeStruct %float %float
  962. %ptr_input_struct = OpTypePointer Input %struct
  963. %var1 = OpVariable %ptr_input_struct Input
  964. %main = OpFunction %void None %void_fn
  965. %entry = OpLabel
  966. OpReturn
  967. OpFunctionEnd
  968. )";
  969. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  970. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  971. }
  972. TEST_F(ValidateInterfacesTest, VulkanLocationsComponentIn64BitVec3) {
  973. const std::string text = R"(
  974. OpCapability Shader
  975. OpCapability Float64
  976. OpMemoryModel Logical GLSL450
  977. OpEntryPoint Fragment %main "main" %var
  978. OpExecutionMode %main OriginUpperLeft
  979. OpDecorate %struct Block
  980. OpMemberDecorate %struct 0 Location 0
  981. OpMemberDecorate %struct 1 Location 1
  982. OpMemberDecorate %struct 1 Component 1
  983. %void = OpTypeVoid
  984. %void_fn = OpTypeFunction %void
  985. %float = OpTypeFloat 32
  986. %double = OpTypeFloat 64
  987. %double3 = OpTypeVector %double 3
  988. %struct = OpTypeStruct %double3 %float
  989. %ptr_input_struct = OpTypePointer Input %struct
  990. %var = OpVariable %ptr_input_struct Input
  991. %main = OpFunction %void None %void_fn
  992. %entry = OpLabel
  993. OpReturn
  994. OpFunctionEnd
  995. )";
  996. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  997. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  998. EXPECT_THAT(getDiagnosticString(),
  999. HasSubstr("Entry-point has conflicting input location assignment "
  1000. "at location 1, component 1"));
  1001. }
  1002. TEST_F(ValidateInterfacesTest, VulkanLocationsComponentAfter64BitVec3) {
  1003. const std::string text = R"(
  1004. OpCapability Shader
  1005. OpCapability Float64
  1006. OpMemoryModel Logical GLSL450
  1007. OpEntryPoint Fragment %main "main" %var
  1008. OpExecutionMode %main OriginUpperLeft
  1009. OpDecorate %struct Block
  1010. OpMemberDecorate %struct 0 Location 0
  1011. OpMemberDecorate %struct 1 Location 1
  1012. OpMemberDecorate %struct 1 Component 2
  1013. %void = OpTypeVoid
  1014. %void_fn = OpTypeFunction %void
  1015. %float = OpTypeFloat 32
  1016. %double = OpTypeFloat 64
  1017. %double3 = OpTypeVector %double 3
  1018. %struct = OpTypeStruct %double3 %float
  1019. %ptr_input_struct = OpTypePointer Input %struct
  1020. %var = OpVariable %ptr_input_struct Input
  1021. %main = OpFunction %void None %void_fn
  1022. %entry = OpLabel
  1023. OpReturn
  1024. OpFunctionEnd
  1025. )";
  1026. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1027. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1028. }
  1029. TEST_F(ValidateInterfacesTest, VulkanLocationsConflictingComponentVariable) {
  1030. const std::string text = R"(
  1031. OpCapability Shader
  1032. OpMemoryModel Logical GLSL450
  1033. OpEntryPoint Fragment %main "main" %var
  1034. OpExecutionMode %main OriginUpperLeft
  1035. OpDecorate %var Location 0
  1036. OpDecorate %var Component 0
  1037. OpDecorate %var Component 1
  1038. %void = OpTypeVoid
  1039. %void_fn = OpTypeFunction %void
  1040. %float = OpTypeFloat 32
  1041. %ptr_input_float = OpTypePointer Input %float
  1042. %var = OpVariable %ptr_input_float Input
  1043. %main = OpFunction %void None %void_fn
  1044. %entry = OpLabel
  1045. OpReturn
  1046. OpFunctionEnd
  1047. )";
  1048. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1049. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1050. EXPECT_THAT(getDiagnosticString(),
  1051. HasSubstr("Variable has conflicting component decorations"));
  1052. }
  1053. TEST_F(ValidateInterfacesTest,
  1054. VulkanLocationsConflictingComponentStructMember) {
  1055. const std::string text = R"(
  1056. OpCapability Shader
  1057. OpMemoryModel Logical GLSL450
  1058. OpEntryPoint Fragment %main "main" %var
  1059. OpExecutionMode %main OriginUpperLeft
  1060. OpDecorate %struct Block
  1061. OpMemberDecorate %struct 0 Location 0
  1062. OpMemberDecorate %struct 0 Component 0
  1063. OpMemberDecorate %struct 0 Component 1
  1064. %void = OpTypeVoid
  1065. %void_fn = OpTypeFunction %void
  1066. %float = OpTypeFloat 32
  1067. %struct = OpTypeStruct %float
  1068. %ptr_input_struct = OpTypePointer Input %struct
  1069. %var = OpVariable %ptr_input_struct Input
  1070. %main = OpFunction %void None %void_fn
  1071. %entry = OpLabel
  1072. OpReturn
  1073. OpFunctionEnd
  1074. )";
  1075. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1076. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1077. EXPECT_THAT(
  1078. getDiagnosticString(),
  1079. HasSubstr("Member index 0 has conflicting component assignments"));
  1080. }
  1081. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
  1082. const std::string text = R"(
  1083. OpCapability Shader
  1084. OpMemoryModel Logical GLSL450
  1085. OpEntryPoint Fragment %main "main" %var1 %var2
  1086. OpExecutionMode %main OriginUpperLeft
  1087. OpDecorate %var1 Location 1
  1088. OpDecorate %var1 Index 1
  1089. OpDecorate %var2 Location 1
  1090. OpDecorate %var2 Index 1
  1091. %void = OpTypeVoid
  1092. %void_fn = OpTypeFunction %void
  1093. %float = OpTypeFloat 32
  1094. %struct = OpTypeStruct %float %float
  1095. %ptr_output_struct = OpTypePointer Output %struct
  1096. %var1 = OpVariable %ptr_output_struct Output
  1097. %var2 = OpVariable %ptr_output_struct Output
  1098. %main = OpFunction %void None %void_fn
  1099. %entry = OpLabel
  1100. OpReturn
  1101. OpFunctionEnd
  1102. )";
  1103. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1104. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1105. EXPECT_THAT(
  1106. getDiagnosticString(),
  1107. HasSubstr("Entry-point has conflicting output location assignment "
  1108. "at location 1"));
  1109. }
  1110. TEST_F(ValidateInterfacesTest,
  1111. VulkanLocationsVariableNoConflictDifferentIndex) {
  1112. const std::string text = R"(
  1113. OpCapability Shader
  1114. OpMemoryModel Logical GLSL450
  1115. OpEntryPoint Fragment %main "main" %var1 %var2
  1116. OpExecutionMode %main OriginUpperLeft
  1117. OpDecorate %var1 Location 1
  1118. OpDecorate %var1 Index 0
  1119. OpDecorate %var2 Location 1
  1120. OpDecorate %var2 Index 1
  1121. %void = OpTypeVoid
  1122. %void_fn = OpTypeFunction %void
  1123. %float = OpTypeFloat 32
  1124. %struct = OpTypeStruct %float %float
  1125. %ptr_output_struct = OpTypePointer Output %struct
  1126. %var1 = OpVariable %ptr_output_struct Output
  1127. %var2 = OpVariable %ptr_output_struct Output
  1128. %main = OpFunction %void None %void_fn
  1129. %entry = OpLabel
  1130. OpReturn
  1131. OpFunctionEnd
  1132. )";
  1133. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1134. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1135. }
  1136. TEST_F(ValidateInterfacesTest, VulkanLocationsIndexGLCompute) {
  1137. const std::string text = R"(
  1138. OpCapability Shader
  1139. OpCapability Geometry
  1140. OpMemoryModel Logical GLSL450
  1141. OpEntryPoint Geometry %main "main" %var1
  1142. OpExecutionMode %main Triangles
  1143. OpExecutionMode %main OutputPoints
  1144. OpDecorate %var1 Location 1
  1145. OpDecorate %var1 Index 1
  1146. %void = OpTypeVoid
  1147. %void_fn = OpTypeFunction %void
  1148. %float = OpTypeFloat 32
  1149. %struct = OpTypeStruct %float %float
  1150. %ptr_output_struct = OpTypePointer Output %struct
  1151. %var1 = OpVariable %ptr_output_struct Output
  1152. %main = OpFunction %void None %void_fn
  1153. %entry = OpLabel
  1154. OpReturn
  1155. OpFunctionEnd
  1156. )";
  1157. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1158. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1159. EXPECT_THAT(
  1160. getDiagnosticString(),
  1161. HasSubstr("Index can only be applied to Fragment output variables"));
  1162. }
  1163. TEST_F(ValidateInterfacesTest, VulkanLocationsIndexInput) {
  1164. const std::string text = R"(
  1165. OpCapability Shader
  1166. OpMemoryModel Logical GLSL450
  1167. OpEntryPoint Fragment %main "main" %var1
  1168. OpExecutionMode %main OriginUpperLeft
  1169. OpDecorate %var1 Location 1
  1170. OpDecorate %var1 Index 1
  1171. %void = OpTypeVoid
  1172. %void_fn = OpTypeFunction %void
  1173. %float = OpTypeFloat 32
  1174. %struct = OpTypeStruct %float %float
  1175. %ptr_input_struct = OpTypePointer Input %struct
  1176. %var1 = OpVariable %ptr_input_struct Input
  1177. %main = OpFunction %void None %void_fn
  1178. %entry = OpLabel
  1179. OpReturn
  1180. OpFunctionEnd
  1181. )";
  1182. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1183. EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1184. EXPECT_THAT(getDiagnosticString(),
  1185. HasSubstr("must be in the Output storage class"));
  1186. }
  1187. TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponent) {
  1188. const std::string text = R"(
  1189. OpCapability Shader
  1190. OpMemoryModel Logical GLSL450
  1191. OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
  1192. OpExecutionMode %4 OriginUpperLeft
  1193. OpDecorate %11 Location 0
  1194. OpDecorate %18 Component 0
  1195. OpDecorate %18 Location 0
  1196. OpDecorate %28 Component 1
  1197. OpDecorate %28 Location 0
  1198. OpDecorate %36 Location 1
  1199. OpDecorate %40 Component 0
  1200. OpDecorate %40 Location 1
  1201. %void = OpTypeVoid
  1202. %3 = OpTypeFunction %void
  1203. %float = OpTypeFloat 32
  1204. %v4float = OpTypeVector %float 4
  1205. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1206. %11 = OpVariable %_ptr_Input_v4float Input
  1207. %_ptr_Output_float = OpTypePointer Output %float
  1208. %18 = OpVariable %_ptr_Output_float Output
  1209. %uint = OpTypeInt 32 0
  1210. %v3float = OpTypeVector %float 3
  1211. %uint_2 = OpConstant %uint 2
  1212. %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
  1213. %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
  1214. %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
  1215. %_ptr_Output_v3float = OpTypePointer Output %v3float
  1216. %36 = OpVariable %_ptr_Input_v4float Input
  1217. %40 = OpVariable %_ptr_Output_float Output
  1218. %4 = OpFunction %void None %3
  1219. %5 = OpLabel
  1220. OpReturn
  1221. OpFunctionEnd
  1222. )";
  1223. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1224. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1225. }
  1226. TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponentBad) {
  1227. const std::string text = R"(
  1228. OpCapability Shader
  1229. OpMemoryModel Logical GLSL450
  1230. OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
  1231. OpExecutionMode %4 OriginUpperLeft
  1232. OpDecorate %11 Location 0
  1233. OpDecorate %18 Component 0
  1234. OpDecorate %18 Location 0
  1235. OpDecorate %28 Component 1
  1236. OpDecorate %28 Location 0
  1237. OpDecorate %36 Location 1
  1238. OpDecorate %40 Component 1
  1239. OpDecorate %40 Location 1
  1240. %void = OpTypeVoid
  1241. %3 = OpTypeFunction %void
  1242. %float = OpTypeFloat 32
  1243. %v4float = OpTypeVector %float 4
  1244. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1245. %11 = OpVariable %_ptr_Input_v4float Input
  1246. %_ptr_Output_float = OpTypePointer Output %float
  1247. %18 = OpVariable %_ptr_Output_float Output
  1248. %uint = OpTypeInt 32 0
  1249. %v3float = OpTypeVector %float 3
  1250. %uint_2 = OpConstant %uint 2
  1251. %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
  1252. %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
  1253. %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
  1254. %_ptr_Output_v3float = OpTypePointer Output %v3float
  1255. %36 = OpVariable %_ptr_Input_v4float Input
  1256. %40 = OpVariable %_ptr_Output_float Output
  1257. %4 = OpFunction %void None %3
  1258. %5 = OpLabel
  1259. OpReturn
  1260. OpFunctionEnd
  1261. )";
  1262. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1263. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1264. EXPECT_THAT(getDiagnosticString(),
  1265. HasSubstr("Entry-point has conflicting output location "
  1266. "assignment at location 1, component 1"));
  1267. }
  1268. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
  1269. const std::string text = R"(
  1270. OpCapability Shader
  1271. OpMemoryModel Logical GLSL450
  1272. OpEntryPoint Fragment %4 "????????" %17
  1273. OpExecutionMode %4 OriginUpperLeft
  1274. OpDecorate %17 Location 4227868160
  1275. %void = OpTypeVoid
  1276. %3 = OpTypeFunction %void
  1277. %float = OpTypeFloat 32
  1278. %v3float = OpTypeVector %float 3
  1279. %_ptr_Input_v3float = OpTypePointer Input %v3float
  1280. %17 = OpVariable %_ptr_Input_v3float Input
  1281. %4 = OpFunction %void None %3
  1282. %5 = OpLabel
  1283. OpUnreachable
  1284. OpFunctionEnd
  1285. )";
  1286. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1287. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1288. }
  1289. TEST_F(ValidateInterfacesTest, VulkanLocationMeshShader) {
  1290. const std::string text = R"(
  1291. OpCapability Shader
  1292. OpCapability MeshShadingNV
  1293. OpExtension "SPV_NV_mesh_shader"
  1294. OpMemoryModel Logical GLSL450
  1295. OpEntryPoint MeshNV %foo "foo" %in
  1296. OpExecutionMode %foo LocalSize 1 1 1
  1297. OpDecorate %block Block
  1298. OpMemberDecorate %block 0 PerTaskNV
  1299. OpMemberDecorate %block 0 Offset 0
  1300. %void = OpTypeVoid
  1301. %int = OpTypeInt 32 0
  1302. %int_32 = OpConstant %int 32
  1303. %array = OpTypeArray %int %int_32
  1304. %block = OpTypeStruct %array
  1305. %ptr_input_block = OpTypePointer Input %block
  1306. %in = OpVariable %ptr_input_block Input
  1307. %void_fn = OpTypeFunction %void
  1308. %foo = OpFunction %void None %void_fn
  1309. %entry = OpLabel
  1310. OpReturn
  1311. OpFunctionEnd
  1312. )";
  1313. CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
  1314. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
  1315. }
  1316. TEST_F(ValidateInterfacesTest, VulkanLocationArrayWithComponent1) {
  1317. const std::string text = R"(
  1318. OpCapability Shader
  1319. OpMemoryModel Logical GLSL450
  1320. OpEntryPoint Fragment %main "main" %in
  1321. OpExecutionMode %main OriginUpperLeft
  1322. OpDecorate %struct Block
  1323. OpMemberDecorate %struct 0 Location 0
  1324. OpMemberDecorate %struct 0 Component 0
  1325. OpMemberDecorate %struct 1 Location 0
  1326. OpMemberDecorate %struct 1 Component 1
  1327. %void = OpTypeVoid
  1328. %void_fn = OpTypeFunction %void
  1329. %float = OpTypeFloat 32
  1330. %int = OpTypeInt 32 0
  1331. %int_2 = OpConstant %int 2
  1332. %float_arr = OpTypeArray %float %int_2
  1333. %struct = OpTypeStruct %float_arr %float_arr
  1334. %ptr = OpTypePointer Input %struct
  1335. %in = OpVariable %ptr Input
  1336. %main = OpFunction %void None %void_fn
  1337. %entry = OpLabel
  1338. OpReturn
  1339. OpFunctionEnd
  1340. )";
  1341. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1342. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1343. }
  1344. TEST_F(ValidateInterfacesTest, VulkanLocationArrayWithComponent2) {
  1345. const std::string text = R"(
  1346. OpCapability Shader
  1347. OpCapability Float64
  1348. OpMemoryModel Logical GLSL450
  1349. OpEntryPoint Fragment %main "main" %in
  1350. OpExecutionMode %main OriginUpperLeft
  1351. OpDecorate %struct Block
  1352. OpMemberDecorate %struct 0 Location 0
  1353. OpMemberDecorate %struct 0 Component 0
  1354. OpMemberDecorate %struct 1 Location 0
  1355. OpMemberDecorate %struct 1 Component 2
  1356. %void = OpTypeVoid
  1357. %void_fn = OpTypeFunction %void
  1358. %float = OpTypeFloat 32
  1359. %double = OpTypeFloat 64
  1360. %int = OpTypeInt 32 0
  1361. %int_2 = OpConstant %int 2
  1362. %double_arr = OpTypeArray %double %int_2
  1363. %struct = OpTypeStruct %float %double_arr
  1364. %ptr = OpTypePointer Input %struct
  1365. %in = OpVariable %ptr Input
  1366. %main = OpFunction %void None %void_fn
  1367. %entry = OpLabel
  1368. OpReturn
  1369. OpFunctionEnd
  1370. )";
  1371. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1372. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1373. }
  1374. TEST_F(ValidateInterfacesTest, DuplicateInterfaceVariableSuccess) {
  1375. const std::string text = R"(
  1376. OpCapability Shader
  1377. OpMemoryModel Logical GLSL450
  1378. OpEntryPoint Fragment %main "main" %in %out %in
  1379. OpExecutionMode %main OriginUpperLeft
  1380. OpDecorate %in Location 0
  1381. OpDecorate %out Location 0
  1382. %void = OpTypeVoid
  1383. %float = OpTypeFloat 32
  1384. %in_ptr = OpTypePointer Input %float
  1385. %out_ptr = OpTypePointer Output %float
  1386. %in = OpVariable %in_ptr Input
  1387. %out = OpVariable %out_ptr Output
  1388. %void_fn = OpTypeFunction %void
  1389. %main = OpFunction %void None %void_fn
  1390. %entry = OpLabel
  1391. OpReturn
  1392. OpFunctionEnd
  1393. )";
  1394. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1395. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1396. }
  1397. TEST_F(ValidateInterfacesTest, StructWithBuiltinsMissingBlock_Bad) {
  1398. // See https://github.com/KhronosGroup/SPIRV-Registry/issues/134
  1399. //
  1400. // When a shader input or output is a struct that does not have Block,
  1401. // then it must have a Location.
  1402. // But BuiltIns must not have locations.
  1403. const std::string text = R"(
  1404. OpCapability Shader
  1405. OpMemoryModel Logical GLSL450
  1406. OpEntryPoint Fragment %main "main" %in
  1407. OpExecutionMode %main OriginUpperLeft
  1408. ; %struct needs a Block decoration
  1409. OpMemberDecorate %struct 0 BuiltIn Position
  1410. %void = OpTypeVoid
  1411. %float = OpTypeFloat 32
  1412. %v4float = OpTypeVector %float 4
  1413. %struct = OpTypeStruct %v4float
  1414. %in_ptr = OpTypePointer Input %struct
  1415. %in = OpVariable %in_ptr Input
  1416. %void_fn = OpTypeFunction %void
  1417. %main = OpFunction %void None %void_fn
  1418. %entry = OpLabel
  1419. OpReturn
  1420. OpFunctionEnd
  1421. )";
  1422. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1423. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1424. EXPECT_THAT(getDiagnosticString(),
  1425. AnyVUID("VUID-StandaloneSpirv-Location-04919"));
  1426. EXPECT_THAT(
  1427. getDiagnosticString(),
  1428. HasSubstr(
  1429. "Interface struct has no Block decoration but has BuiltIn members."));
  1430. }
  1431. } // namespace
  1432. } // namespace val
  1433. } // namespace spvtools