val_interfaces_test.cpp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  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. HasSubstr("Members cannot be assigned a location"));
  415. }
  416. TEST_F(ValidateInterfacesTest, VulkanLocationsMemberAndSubMemberAssigned) {
  417. const std::string text = R"(
  418. OpCapability Shader
  419. OpMemoryModel Logical GLSL450
  420. OpEntryPoint Fragment %main "main" %var
  421. OpExecutionMode %main OriginUpperLeft
  422. OpDecorate %outer Block
  423. OpMemberDecorate %outer 0 Location 0
  424. OpMemberDecorate %struct 0 Location 0
  425. %void = OpTypeVoid
  426. %void_fn = OpTypeFunction %void
  427. %float = OpTypeFloat 32
  428. %struct = OpTypeStruct %float
  429. %outer = OpTypeStruct %struct
  430. %ptr_input_outer = OpTypePointer Input %outer
  431. %var = OpVariable %ptr_input_outer Input
  432. %main = OpFunction %void None %void_fn
  433. %entry = OpLabel
  434. OpReturn
  435. OpFunctionEnd
  436. )";
  437. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  438. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  439. EXPECT_THAT(getDiagnosticString(),
  440. HasSubstr("Members cannot be assigned a location"));
  441. }
  442. TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentStructMember) {
  443. const std::string text = R"(
  444. OpCapability Shader
  445. OpMemoryModel Logical GLSL450
  446. OpEntryPoint Fragment %main "main" %var
  447. OpExecutionMode %main OriginUpperLeft
  448. OpDecorate %struct Block
  449. OpMemberDecorate %struct 1 Location 0
  450. OpMemberDecorate %struct 1 Location 1
  451. %void = OpTypeVoid
  452. %void_fn = OpTypeFunction %void
  453. %float = OpTypeFloat 32
  454. %struct = OpTypeStruct %float %float
  455. %ptr_input_struct = OpTypePointer Input %struct
  456. %var = OpVariable %ptr_input_struct Input
  457. %main = OpFunction %void None %void_fn
  458. %entry = OpLabel
  459. OpReturn
  460. OpFunctionEnd
  461. )";
  462. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  463. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  464. EXPECT_THAT(getDiagnosticString(),
  465. HasSubstr("Member index 1 has conflicting location assignments"));
  466. }
  467. TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
  468. const std::string text = R"(
  469. OpCapability Shader
  470. OpMemoryModel Logical GLSL450
  471. OpEntryPoint Fragment %main "main" %var
  472. OpExecutionMode %main OriginUpperLeft
  473. OpDecorate %struct Block
  474. OpMemberDecorate %struct 1 Location 1
  475. %void = OpTypeVoid
  476. %void_fn = OpTypeFunction %void
  477. %float = OpTypeFloat 32
  478. %struct = OpTypeStruct %float %float
  479. %ptr_input_struct = OpTypePointer Input %struct
  480. %var = OpVariable %ptr_input_struct Input
  481. %main = OpFunction %void None %void_fn
  482. %entry = OpLabel
  483. OpReturn
  484. OpFunctionEnd
  485. )";
  486. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  487. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  488. EXPECT_THAT(getDiagnosticString(),
  489. HasSubstr("Member index 0 is missing a location assignment"));
  490. }
  491. TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentNonBlockStruct) {
  492. const std::string text = R"(
  493. OpCapability Shader
  494. OpMemoryModel Logical GLSL450
  495. OpEntryPoint Fragment %main "main" %var
  496. OpExecutionMode %main OriginUpperLeft
  497. %void = OpTypeVoid
  498. %void_fn = OpTypeFunction %void
  499. %float = OpTypeFloat 32
  500. %struct = OpTypeStruct %float %float
  501. %ptr_input_struct = OpTypePointer Input %struct
  502. %var = OpVariable %ptr_input_struct Input
  503. %main = OpFunction %void None %void_fn
  504. %entry = OpLabel
  505. OpReturn
  506. OpFunctionEnd
  507. )";
  508. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  509. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  510. EXPECT_THAT(getDiagnosticString(),
  511. HasSubstr("Variable must be decorated with a location"));
  512. }
  513. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictInput) {
  514. const std::string text = R"(
  515. OpCapability Shader
  516. OpMemoryModel Logical GLSL450
  517. OpEntryPoint Fragment %main "main" %var1 %var2
  518. OpExecutionMode %main OriginUpperLeft
  519. OpDecorate %var1 Location 0
  520. OpDecorate %var2 Location 0
  521. %void = OpTypeVoid
  522. %void_fn = OpTypeFunction %void
  523. %float = OpTypeFloat 32
  524. %struct = OpTypeStruct %float %float
  525. %ptr_input_struct = OpTypePointer Input %struct
  526. %var1 = OpVariable %ptr_input_struct Input
  527. %var2 = OpVariable %ptr_input_struct Input
  528. %main = OpFunction %void None %void_fn
  529. %entry = OpLabel
  530. OpReturn
  531. OpFunctionEnd
  532. )";
  533. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  534. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  535. EXPECT_THAT(getDiagnosticString(),
  536. HasSubstr("Entry-point has conflicting input location assignment "
  537. "at location 0"));
  538. }
  539. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutput) {
  540. const std::string text = R"(
  541. OpCapability Shader
  542. OpMemoryModel Logical GLSL450
  543. OpEntryPoint Fragment %main "main" %var1 %var2
  544. OpExecutionMode %main OriginUpperLeft
  545. OpDecorate %var1 Location 1
  546. OpDecorate %var2 Location 1
  547. %void = OpTypeVoid
  548. %void_fn = OpTypeFunction %void
  549. %float = OpTypeFloat 32
  550. %struct = OpTypeStruct %float %float
  551. %ptr_output_struct = OpTypePointer Output %struct
  552. %var1 = OpVariable %ptr_output_struct Output
  553. %var2 = OpVariable %ptr_output_struct Output
  554. %main = OpFunction %void None %void_fn
  555. %entry = OpLabel
  556. OpReturn
  557. OpFunctionEnd
  558. )";
  559. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  560. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  561. EXPECT_THAT(
  562. getDiagnosticString(),
  563. HasSubstr("Entry-point has conflicting output location assignment "
  564. "at location 1"));
  565. }
  566. TEST_F(ValidateInterfacesTest,
  567. VulkanLocationsSameLocationInputAndOutputNoConflict) {
  568. const std::string text = R"(
  569. OpCapability Shader
  570. OpMemoryModel Logical GLSL450
  571. OpEntryPoint Fragment %main "main" %var1 %var2
  572. OpExecutionMode %main OriginUpperLeft
  573. OpDecorate %var1 Location 1
  574. OpDecorate %var2 Location 1
  575. %void = OpTypeVoid
  576. %void_fn = OpTypeFunction %void
  577. %float = OpTypeFloat 32
  578. %struct = OpTypeStruct %float %float
  579. %ptr_input_struct = OpTypePointer Input %struct
  580. %ptr_output_struct = OpTypePointer Output %struct
  581. %var1 = OpVariable %ptr_input_struct Input
  582. %var2 = OpVariable %ptr_output_struct Output
  583. %main = OpFunction %void None %void_fn
  584. %entry = OpLabel
  585. OpReturn
  586. OpFunctionEnd
  587. )";
  588. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  589. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  590. }
  591. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableInGap) {
  592. const std::string text = R"(
  593. OpCapability Shader
  594. OpMemoryModel Logical GLSL450
  595. OpEntryPoint Fragment %main "main" %var1 %var2
  596. OpExecutionMode %main OriginUpperLeft
  597. OpDecorate %struct Block
  598. OpMemberDecorate %struct 0 Location 0
  599. OpMemberDecorate %struct 1 Location 2
  600. OpDecorate %var2 Location 1
  601. %void = OpTypeVoid
  602. %void_fn = OpTypeFunction %void
  603. %float = OpTypeFloat 32
  604. %struct = OpTypeStruct %float %float
  605. %ptr_input_struct = OpTypePointer Input %struct
  606. %ptr_input_float = OpTypePointer Input %float
  607. %var1 = OpVariable %ptr_input_struct Input
  608. %var2 = OpVariable %ptr_input_float Input
  609. %main = OpFunction %void None %void_fn
  610. %entry = OpLabel
  611. OpReturn
  612. OpFunctionEnd
  613. )";
  614. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  615. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  616. }
  617. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeFloatVectorConflict) {
  618. const std::string text = R"(
  619. OpCapability Shader
  620. OpCapability Float64
  621. OpMemoryModel Logical GLSL450
  622. OpEntryPoint Fragment %main "main" %var1 %var2
  623. OpExecutionMode %main OriginUpperLeft
  624. OpDecorate %var1 Location 0
  625. OpDecorate %var2 Location 1
  626. %void = OpTypeVoid
  627. %void_fn = OpTypeFunction %void
  628. %float = OpTypeFloat 32
  629. %double = OpTypeFloat 64
  630. %vector = OpTypeVector %double 3
  631. %ptr_input_float = OpTypePointer Input %float
  632. %ptr_input_vector = OpTypePointer Input %vector
  633. %var1 = OpVariable %ptr_input_vector Input
  634. %var2 = OpVariable %ptr_input_float Input
  635. %main = OpFunction %void None %void_fn
  636. %entry = OpLabel
  637. OpReturn
  638. OpFunctionEnd
  639. )";
  640. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  641. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  642. EXPECT_THAT(getDiagnosticString(),
  643. HasSubstr("Entry-point has conflicting input location assignment "
  644. "at location 1"));
  645. }
  646. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeIntVectorConflict) {
  647. const std::string text = R"(
  648. OpCapability Shader
  649. OpCapability Int64
  650. OpMemoryModel Logical GLSL450
  651. OpEntryPoint Fragment %main "main" %var1 %var2
  652. OpExecutionMode %main OriginUpperLeft
  653. OpDecorate %var1 Location 0
  654. OpDecorate %var2 Location 1
  655. %void = OpTypeVoid
  656. %void_fn = OpTypeFunction %void
  657. %float = OpTypeFloat 32
  658. %long = OpTypeInt 64 0
  659. %vector = OpTypeVector %long 4
  660. %ptr_input_float = OpTypePointer Input %float
  661. %ptr_input_vector = OpTypePointer Input %vector
  662. %var1 = OpVariable %ptr_input_vector Input
  663. %var2 = OpVariable %ptr_input_float Input
  664. %main = OpFunction %void None %void_fn
  665. %entry = OpLabel
  666. OpReturn
  667. OpFunctionEnd
  668. )";
  669. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  670. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  671. EXPECT_THAT(getDiagnosticString(),
  672. HasSubstr("Entry-point has conflicting input location assignment "
  673. "at location 1"));
  674. }
  675. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix2x2Conflict) {
  676. const std::string text = R"(
  677. OpCapability Shader
  678. OpMemoryModel Logical GLSL450
  679. OpEntryPoint Fragment %main "main" %var1 %var2
  680. OpExecutionMode %main OriginUpperLeft
  681. OpDecorate %var1 Location 0
  682. OpDecorate %var2 Location 1
  683. %void = OpTypeVoid
  684. %void_fn = OpTypeFunction %void
  685. %float = OpTypeFloat 32
  686. %vector = OpTypeVector %float 2
  687. %matrix = OpTypeMatrix %vector 2
  688. %ptr_input_float = OpTypePointer Input %float
  689. %ptr_input_matrix = OpTypePointer Input %matrix
  690. %var1 = OpVariable %ptr_input_matrix Input
  691. %var2 = OpVariable %ptr_input_float Input
  692. %main = OpFunction %void None %void_fn
  693. %entry = OpLabel
  694. OpReturn
  695. OpFunctionEnd
  696. )";
  697. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  698. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  699. EXPECT_THAT(getDiagnosticString(),
  700. HasSubstr("Entry-point has conflicting input location assignment "
  701. "at location 1"));
  702. }
  703. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix3x3Conflict) {
  704. const std::string text = R"(
  705. OpCapability Shader
  706. OpMemoryModel Logical GLSL450
  707. OpEntryPoint Fragment %main "main" %var1 %var2
  708. OpExecutionMode %main OriginUpperLeft
  709. OpDecorate %var1 Location 0
  710. OpDecorate %var2 Location 2
  711. %void = OpTypeVoid
  712. %void_fn = OpTypeFunction %void
  713. %float = OpTypeFloat 32
  714. %vector = OpTypeVector %float 3
  715. %matrix = OpTypeMatrix %vector 3
  716. %ptr_input_float = OpTypePointer Input %float
  717. %ptr_input_matrix = OpTypePointer Input %matrix
  718. %var1 = OpVariable %ptr_input_matrix Input
  719. %var2 = OpVariable %ptr_input_float Input
  720. %main = OpFunction %void None %void_fn
  721. %entry = OpLabel
  722. OpReturn
  723. OpFunctionEnd
  724. )";
  725. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  726. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  727. EXPECT_THAT(getDiagnosticString(),
  728. HasSubstr("Entry-point has conflicting input location assignment "
  729. "at location 2"));
  730. }
  731. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Conflict) {
  732. const std::string text = R"(
  733. OpCapability Shader
  734. OpMemoryModel Logical GLSL450
  735. OpEntryPoint Fragment %main "main" %var1 %var2
  736. OpExecutionMode %main OriginUpperLeft
  737. OpDecorate %var1 Location 0
  738. OpDecorate %var2 Location 3
  739. %void = OpTypeVoid
  740. %void_fn = OpTypeFunction %void
  741. %float = OpTypeFloat 32
  742. %vector = OpTypeVector %float 4
  743. %matrix = OpTypeMatrix %vector 4
  744. %ptr_input_float = OpTypePointer Input %float
  745. %ptr_input_matrix = OpTypePointer Input %matrix
  746. %var1 = OpVariable %ptr_input_matrix Input
  747. %var2 = OpVariable %ptr_input_float Input
  748. %main = OpFunction %void None %void_fn
  749. %entry = OpLabel
  750. OpReturn
  751. OpFunctionEnd
  752. )";
  753. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  754. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  755. EXPECT_THAT(getDiagnosticString(),
  756. HasSubstr("Entry-point has conflicting input location assignment "
  757. "at location 3"));
  758. }
  759. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix2x2Conflict) {
  760. const std::string text = R"(
  761. OpCapability Shader
  762. OpCapability Float64
  763. OpMemoryModel Logical GLSL450
  764. OpEntryPoint Fragment %main "main" %var1 %var2
  765. OpExecutionMode %main OriginUpperLeft
  766. OpDecorate %var1 Location 0
  767. OpDecorate %var2 Location 1
  768. %void = OpTypeVoid
  769. %void_fn = OpTypeFunction %void
  770. %float = OpTypeFloat 32
  771. %double = OpTypeFloat 64
  772. %vector = OpTypeVector %double 2
  773. %matrix = OpTypeMatrix %vector 2
  774. %ptr_input_float = OpTypePointer Input %float
  775. %ptr_input_matrix = OpTypePointer Input %matrix
  776. %var1 = OpVariable %ptr_input_matrix Input
  777. %var2 = OpVariable %ptr_input_float Input
  778. %main = OpFunction %void None %void_fn
  779. %entry = OpLabel
  780. OpReturn
  781. OpFunctionEnd
  782. )";
  783. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  784. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  785. EXPECT_THAT(getDiagnosticString(),
  786. HasSubstr("Entry-point has conflicting input location assignment "
  787. "at location 1"));
  788. }
  789. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix3x3Conflict) {
  790. const std::string text = R"(
  791. OpCapability Shader
  792. OpCapability Float64
  793. OpMemoryModel Logical GLSL450
  794. OpEntryPoint Fragment %main "main" %var1 %var2
  795. OpExecutionMode %main OriginUpperLeft
  796. OpDecorate %var1 Location 0
  797. OpDecorate %var2 Location 5
  798. %void = OpTypeVoid
  799. %void_fn = OpTypeFunction %void
  800. %float = OpTypeFloat 32
  801. %double = OpTypeFloat 64
  802. %vector = OpTypeVector %double 3
  803. %matrix = OpTypeMatrix %vector 3
  804. %ptr_input_float = OpTypePointer Input %float
  805. %ptr_input_matrix = OpTypePointer Input %matrix
  806. %var1 = OpVariable %ptr_input_matrix Input
  807. %var2 = OpVariable %ptr_input_float Input
  808. %main = OpFunction %void None %void_fn
  809. %entry = OpLabel
  810. OpReturn
  811. OpFunctionEnd
  812. )";
  813. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  814. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  815. EXPECT_THAT(getDiagnosticString(),
  816. HasSubstr("Entry-point has conflicting input location assignment "
  817. "at location 5"));
  818. }
  819. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix4x4Conflict) {
  820. const std::string text = R"(
  821. OpCapability Shader
  822. OpCapability Float64
  823. OpMemoryModel Logical GLSL450
  824. OpEntryPoint Fragment %main "main" %var1 %var2
  825. OpExecutionMode %main OriginUpperLeft
  826. OpDecorate %var1 Location 0
  827. OpDecorate %var2 Location 7
  828. %void = OpTypeVoid
  829. %void_fn = OpTypeFunction %void
  830. %float = OpTypeFloat 32
  831. %double = OpTypeFloat 64
  832. %vector = OpTypeVector %double 4
  833. %matrix = OpTypeMatrix %vector 4
  834. %ptr_input_float = OpTypePointer Input %float
  835. %ptr_input_matrix = OpTypePointer Input %matrix
  836. %var1 = OpVariable %ptr_input_matrix Input
  837. %var2 = OpVariable %ptr_input_float Input
  838. %main = OpFunction %void None %void_fn
  839. %entry = OpLabel
  840. OpReturn
  841. OpFunctionEnd
  842. )";
  843. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  844. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  845. EXPECT_THAT(getDiagnosticString(),
  846. HasSubstr("Entry-point has conflicting input location assignment "
  847. "at location 7"));
  848. }
  849. TEST_F(ValidateInterfacesTest, VulkanLocationsArray2Conflict) {
  850. const std::string text = R"(
  851. OpCapability Shader
  852. OpMemoryModel Logical GLSL450
  853. OpEntryPoint Fragment %main "main" %var1 %var2
  854. OpExecutionMode %main OriginUpperLeft
  855. OpDecorate %var1 Location 0
  856. OpDecorate %var2 Location 1
  857. %void = OpTypeVoid
  858. %void_fn = OpTypeFunction %void
  859. %float = OpTypeFloat 32
  860. %int = OpTypeInt 32 0
  861. %int_2 = OpConstant %int 2
  862. %array = OpTypeArray %int %int_2
  863. %struct = OpTypeStruct %array
  864. %ptr_input_float = OpTypePointer Input %float
  865. %ptr_input_struct = OpTypePointer Input %struct
  866. %var1 = OpVariable %ptr_input_struct Input
  867. %var2 = OpVariable %ptr_input_float Input
  868. %main = OpFunction %void None %void_fn
  869. %entry = OpLabel
  870. OpReturn
  871. OpFunctionEnd
  872. )";
  873. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  874. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  875. EXPECT_THAT(getDiagnosticString(),
  876. HasSubstr("Entry-point has conflicting input location assignment "
  877. "at location 1"));
  878. }
  879. TEST_F(ValidateInterfacesTest, VulkanLocationsArray4Conflict) {
  880. const std::string text = R"(
  881. OpCapability Shader
  882. OpMemoryModel Logical GLSL450
  883. OpEntryPoint Fragment %main "main" %var1 %var2
  884. OpExecutionMode %main OriginUpperLeft
  885. OpDecorate %var1 Location 0
  886. OpDecorate %var2 Location 3
  887. %void = OpTypeVoid
  888. %void_fn = OpTypeFunction %void
  889. %float = OpTypeFloat 32
  890. %int = OpTypeInt 32 0
  891. %int_4 = OpConstant %int 4
  892. %array = OpTypeArray %int %int_4
  893. %struct = OpTypeStruct %array
  894. %ptr_input_float = OpTypePointer Input %float
  895. %ptr_input_struct = OpTypePointer Input %struct
  896. %var1 = OpVariable %ptr_input_struct Input
  897. %var2 = OpVariable %ptr_input_float Input
  898. %main = OpFunction %void None %void_fn
  899. %entry = OpLabel
  900. OpReturn
  901. OpFunctionEnd
  902. )";
  903. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  904. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  905. EXPECT_THAT(getDiagnosticString(),
  906. HasSubstr("Entry-point has conflicting input location assignment "
  907. "at location 3"));
  908. }
  909. TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Array4Conflict) {
  910. const std::string text = R"(
  911. OpCapability Shader
  912. OpMemoryModel Logical GLSL450
  913. OpEntryPoint Fragment %main "main" %var1 %var2
  914. OpExecutionMode %main OriginUpperLeft
  915. OpDecorate %var1 Location 0
  916. OpDecorate %var2 Location 15
  917. %void = OpTypeVoid
  918. %void_fn = OpTypeFunction %void
  919. %float = OpTypeFloat 32
  920. %int = OpTypeInt 32 0
  921. %int_4 = OpConstant %int 4
  922. %vector = OpTypeVector %float 4
  923. %matrix = OpTypeMatrix %vector 4
  924. %array = OpTypeArray %matrix %int_4
  925. %struct = OpTypeStruct %array
  926. %ptr_input_float = OpTypePointer Input %float
  927. %ptr_input_struct = OpTypePointer Input %struct
  928. %var1 = OpVariable %ptr_input_struct Input
  929. %var2 = OpVariable %ptr_input_float Input
  930. %main = OpFunction %void None %void_fn
  931. %entry = OpLabel
  932. OpReturn
  933. OpFunctionEnd
  934. )";
  935. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  936. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  937. EXPECT_THAT(getDiagnosticString(),
  938. HasSubstr("Entry-point has conflicting input location assignment "
  939. "at location 15"));
  940. }
  941. TEST_F(ValidateInterfacesTest, VulkanLocationsComponentDisambiguates) {
  942. const std::string text = R"(
  943. OpCapability Shader
  944. OpMemoryModel Logical GLSL450
  945. OpEntryPoint Fragment %main "main" %var1
  946. OpExecutionMode %main OriginUpperLeft
  947. OpDecorate %struct Block
  948. OpMemberDecorate %struct 0 Location 0
  949. OpMemberDecorate %struct 0 Component 0
  950. OpMemberDecorate %struct 1 Location 0
  951. OpMemberDecorate %struct 1 Component 1
  952. %void = OpTypeVoid
  953. %void_fn = OpTypeFunction %void
  954. %float = OpTypeFloat 32
  955. %struct = OpTypeStruct %float %float
  956. %ptr_input_struct = OpTypePointer Input %struct
  957. %var1 = OpVariable %ptr_input_struct Input
  958. %main = OpFunction %void None %void_fn
  959. %entry = OpLabel
  960. OpReturn
  961. OpFunctionEnd
  962. )";
  963. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  964. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  965. }
  966. TEST_F(ValidateInterfacesTest, VulkanLocationsComponentIn64BitVec3) {
  967. const std::string text = R"(
  968. OpCapability Shader
  969. OpCapability Float64
  970. OpMemoryModel Logical GLSL450
  971. OpEntryPoint Fragment %main "main" %var
  972. OpExecutionMode %main OriginUpperLeft
  973. OpDecorate %struct Block
  974. OpMemberDecorate %struct 0 Location 0
  975. OpMemberDecorate %struct 1 Location 1
  976. OpMemberDecorate %struct 1 Component 1
  977. %void = OpTypeVoid
  978. %void_fn = OpTypeFunction %void
  979. %float = OpTypeFloat 32
  980. %double = OpTypeFloat 64
  981. %double3 = OpTypeVector %double 3
  982. %struct = OpTypeStruct %double3 %float
  983. %ptr_input_struct = OpTypePointer Input %struct
  984. %var = OpVariable %ptr_input_struct Input
  985. %main = OpFunction %void None %void_fn
  986. %entry = OpLabel
  987. OpReturn
  988. OpFunctionEnd
  989. )";
  990. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  991. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  992. EXPECT_THAT(getDiagnosticString(),
  993. HasSubstr("Entry-point has conflicting input location assignment "
  994. "at location 1, component 1"));
  995. }
  996. TEST_F(ValidateInterfacesTest, VulkanLocationsComponentAfter64BitVec3) {
  997. const std::string text = R"(
  998. OpCapability Shader
  999. OpCapability Float64
  1000. OpMemoryModel Logical GLSL450
  1001. OpEntryPoint Fragment %main "main" %var
  1002. OpExecutionMode %main OriginUpperLeft
  1003. OpDecorate %struct Block
  1004. OpMemberDecorate %struct 0 Location 0
  1005. OpMemberDecorate %struct 1 Location 1
  1006. OpMemberDecorate %struct 1 Component 2
  1007. %void = OpTypeVoid
  1008. %void_fn = OpTypeFunction %void
  1009. %float = OpTypeFloat 32
  1010. %double = OpTypeFloat 64
  1011. %double3 = OpTypeVector %double 3
  1012. %struct = OpTypeStruct %double3 %float
  1013. %ptr_input_struct = OpTypePointer Input %struct
  1014. %var = OpVariable %ptr_input_struct Input
  1015. %main = OpFunction %void None %void_fn
  1016. %entry = OpLabel
  1017. OpReturn
  1018. OpFunctionEnd
  1019. )";
  1020. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1021. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1022. }
  1023. TEST_F(ValidateInterfacesTest, VulkanLocationsConflictingComponentVariable) {
  1024. const std::string text = R"(
  1025. OpCapability Shader
  1026. OpMemoryModel Logical GLSL450
  1027. OpEntryPoint Fragment %main "main" %var
  1028. OpExecutionMode %main OriginUpperLeft
  1029. OpDecorate %var Location 0
  1030. OpDecorate %var Component 0
  1031. OpDecorate %var Component 1
  1032. %void = OpTypeVoid
  1033. %void_fn = OpTypeFunction %void
  1034. %float = OpTypeFloat 32
  1035. %ptr_input_float = OpTypePointer Input %float
  1036. %var = OpVariable %ptr_input_float Input
  1037. %main = OpFunction %void None %void_fn
  1038. %entry = OpLabel
  1039. OpReturn
  1040. OpFunctionEnd
  1041. )";
  1042. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1043. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1044. EXPECT_THAT(getDiagnosticString(),
  1045. HasSubstr("Variable has conflicting component decorations"));
  1046. }
  1047. TEST_F(ValidateInterfacesTest,
  1048. VulkanLocationsConflictingComponentStructMember) {
  1049. const std::string text = R"(
  1050. OpCapability Shader
  1051. OpMemoryModel Logical GLSL450
  1052. OpEntryPoint Fragment %main "main" %var
  1053. OpExecutionMode %main OriginUpperLeft
  1054. OpDecorate %struct Block
  1055. OpMemberDecorate %struct 0 Location 0
  1056. OpMemberDecorate %struct 0 Component 0
  1057. OpMemberDecorate %struct 0 Component 1
  1058. %void = OpTypeVoid
  1059. %void_fn = OpTypeFunction %void
  1060. %float = OpTypeFloat 32
  1061. %struct = OpTypeStruct %float
  1062. %ptr_input_struct = OpTypePointer Input %struct
  1063. %var = OpVariable %ptr_input_struct Input
  1064. %main = OpFunction %void None %void_fn
  1065. %entry = OpLabel
  1066. OpReturn
  1067. OpFunctionEnd
  1068. )";
  1069. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1070. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1071. EXPECT_THAT(
  1072. getDiagnosticString(),
  1073. HasSubstr("Member index 0 has conflicting component assignments"));
  1074. }
  1075. TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
  1076. const std::string text = R"(
  1077. OpCapability Shader
  1078. OpMemoryModel Logical GLSL450
  1079. OpEntryPoint Fragment %main "main" %var1 %var2
  1080. OpExecutionMode %main OriginUpperLeft
  1081. OpDecorate %var1 Location 1
  1082. OpDecorate %var1 Index 1
  1083. OpDecorate %var2 Location 1
  1084. OpDecorate %var2 Index 1
  1085. %void = OpTypeVoid
  1086. %void_fn = OpTypeFunction %void
  1087. %float = OpTypeFloat 32
  1088. %struct = OpTypeStruct %float %float
  1089. %ptr_output_struct = OpTypePointer Output %struct
  1090. %var1 = OpVariable %ptr_output_struct Output
  1091. %var2 = OpVariable %ptr_output_struct Output
  1092. %main = OpFunction %void None %void_fn
  1093. %entry = OpLabel
  1094. OpReturn
  1095. OpFunctionEnd
  1096. )";
  1097. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1098. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1099. EXPECT_THAT(
  1100. getDiagnosticString(),
  1101. HasSubstr("Entry-point has conflicting output location assignment "
  1102. "at location 1"));
  1103. }
  1104. TEST_F(ValidateInterfacesTest,
  1105. VulkanLocationsVariableNoConflictDifferentIndex) {
  1106. const std::string text = R"(
  1107. OpCapability Shader
  1108. OpMemoryModel Logical GLSL450
  1109. OpEntryPoint Fragment %main "main" %var1 %var2
  1110. OpExecutionMode %main OriginUpperLeft
  1111. OpDecorate %var1 Location 1
  1112. OpDecorate %var1 Index 0
  1113. OpDecorate %var2 Location 1
  1114. OpDecorate %var2 Index 1
  1115. %void = OpTypeVoid
  1116. %void_fn = OpTypeFunction %void
  1117. %float = OpTypeFloat 32
  1118. %struct = OpTypeStruct %float %float
  1119. %ptr_output_struct = OpTypePointer Output %struct
  1120. %var1 = OpVariable %ptr_output_struct Output
  1121. %var2 = OpVariable %ptr_output_struct Output
  1122. %main = OpFunction %void None %void_fn
  1123. %entry = OpLabel
  1124. OpReturn
  1125. OpFunctionEnd
  1126. )";
  1127. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1128. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1129. }
  1130. TEST_F(ValidateInterfacesTest, VulkanLocationsIndexGLCompute) {
  1131. const std::string text = R"(
  1132. OpCapability Shader
  1133. OpCapability Geometry
  1134. OpMemoryModel Logical GLSL450
  1135. OpEntryPoint Geometry %main "main" %var1
  1136. OpExecutionMode %main Triangles
  1137. OpExecutionMode %main OutputPoints
  1138. OpDecorate %var1 Location 1
  1139. OpDecorate %var1 Index 1
  1140. %void = OpTypeVoid
  1141. %void_fn = OpTypeFunction %void
  1142. %float = OpTypeFloat 32
  1143. %struct = OpTypeStruct %float %float
  1144. %ptr_output_struct = OpTypePointer Output %struct
  1145. %var1 = OpVariable %ptr_output_struct Output
  1146. %main = OpFunction %void None %void_fn
  1147. %entry = OpLabel
  1148. OpReturn
  1149. OpFunctionEnd
  1150. )";
  1151. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1152. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1153. EXPECT_THAT(
  1154. getDiagnosticString(),
  1155. HasSubstr("Index can only be applied to Fragment output variables"));
  1156. }
  1157. TEST_F(ValidateInterfacesTest, VulkanLocationsIndexInput) {
  1158. const std::string text = R"(
  1159. OpCapability Shader
  1160. OpMemoryModel Logical GLSL450
  1161. OpEntryPoint Fragment %main "main" %var1
  1162. OpExecutionMode %main OriginUpperLeft
  1163. OpDecorate %var1 Location 1
  1164. OpDecorate %var1 Index 1
  1165. %void = OpTypeVoid
  1166. %void_fn = OpTypeFunction %void
  1167. %float = OpTypeFloat 32
  1168. %struct = OpTypeStruct %float %float
  1169. %ptr_input_struct = OpTypePointer Input %struct
  1170. %var1 = OpVariable %ptr_input_struct Input
  1171. %main = OpFunction %void None %void_fn
  1172. %entry = OpLabel
  1173. OpReturn
  1174. OpFunctionEnd
  1175. )";
  1176. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1177. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1178. EXPECT_THAT(
  1179. getDiagnosticString(),
  1180. HasSubstr("Index can only be applied to Fragment output variables"));
  1181. }
  1182. TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponent) {
  1183. const std::string text = R"(
  1184. OpCapability Shader
  1185. OpMemoryModel Logical GLSL450
  1186. OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
  1187. OpExecutionMode %4 OriginUpperLeft
  1188. OpDecorate %11 Location 0
  1189. OpDecorate %18 Component 0
  1190. OpDecorate %18 Location 0
  1191. OpDecorate %28 Component 1
  1192. OpDecorate %28 Location 0
  1193. OpDecorate %36 Location 1
  1194. OpDecorate %40 Component 0
  1195. OpDecorate %40 Location 1
  1196. %void = OpTypeVoid
  1197. %3 = OpTypeFunction %void
  1198. %float = OpTypeFloat 32
  1199. %v4float = OpTypeVector %float 4
  1200. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1201. %11 = OpVariable %_ptr_Input_v4float Input
  1202. %_ptr_Output_float = OpTypePointer Output %float
  1203. %18 = OpVariable %_ptr_Output_float Output
  1204. %uint = OpTypeInt 32 0
  1205. %v3float = OpTypeVector %float 3
  1206. %uint_2 = OpConstant %uint 2
  1207. %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
  1208. %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
  1209. %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
  1210. %_ptr_Output_v3float = OpTypePointer Output %v3float
  1211. %36 = OpVariable %_ptr_Input_v4float Input
  1212. %40 = OpVariable %_ptr_Output_float Output
  1213. %4 = OpFunction %void None %3
  1214. %5 = OpLabel
  1215. OpReturn
  1216. OpFunctionEnd
  1217. )";
  1218. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1219. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1220. }
  1221. TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponentBad) {
  1222. const std::string text = R"(
  1223. OpCapability Shader
  1224. OpMemoryModel Logical GLSL450
  1225. OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
  1226. OpExecutionMode %4 OriginUpperLeft
  1227. OpDecorate %11 Location 0
  1228. OpDecorate %18 Component 0
  1229. OpDecorate %18 Location 0
  1230. OpDecorate %28 Component 1
  1231. OpDecorate %28 Location 0
  1232. OpDecorate %36 Location 1
  1233. OpDecorate %40 Component 1
  1234. OpDecorate %40 Location 1
  1235. %void = OpTypeVoid
  1236. %3 = OpTypeFunction %void
  1237. %float = OpTypeFloat 32
  1238. %v4float = OpTypeVector %float 4
  1239. %_ptr_Input_v4float = OpTypePointer Input %v4float
  1240. %11 = OpVariable %_ptr_Input_v4float Input
  1241. %_ptr_Output_float = OpTypePointer Output %float
  1242. %18 = OpVariable %_ptr_Output_float Output
  1243. %uint = OpTypeInt 32 0
  1244. %v3float = OpTypeVector %float 3
  1245. %uint_2 = OpConstant %uint 2
  1246. %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
  1247. %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
  1248. %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
  1249. %_ptr_Output_v3float = OpTypePointer Output %v3float
  1250. %36 = OpVariable %_ptr_Input_v4float Input
  1251. %40 = OpVariable %_ptr_Output_float Output
  1252. %4 = OpFunction %void None %3
  1253. %5 = OpLabel
  1254. OpReturn
  1255. OpFunctionEnd
  1256. )";
  1257. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1258. EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1259. EXPECT_THAT(getDiagnosticString(),
  1260. HasSubstr("Entry-point has conflicting output location "
  1261. "assignment at location 1, component 1"));
  1262. }
  1263. TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
  1264. const std::string text = R"(
  1265. OpCapability Shader
  1266. OpMemoryModel Logical GLSL450
  1267. OpEntryPoint Fragment %4 "????????" %17
  1268. OpExecutionMode %4 OriginUpperLeft
  1269. OpDecorate %17 Location 4227868160
  1270. %void = OpTypeVoid
  1271. %3 = OpTypeFunction %void
  1272. %float = OpTypeFloat 32
  1273. %v3float = OpTypeVector %float 3
  1274. %_ptr_Input_v3float = OpTypePointer Input %v3float
  1275. %17 = OpVariable %_ptr_Input_v3float Input
  1276. %4 = OpFunction %void None %3
  1277. %5 = OpLabel
  1278. OpUnreachable
  1279. OpFunctionEnd
  1280. )";
  1281. CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
  1282. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
  1283. }
  1284. TEST_F(ValidateInterfacesTest, VulkanLocationMeshShader) {
  1285. const std::string text = R"(
  1286. OpCapability Shader
  1287. OpCapability MeshShadingNV
  1288. OpExtension "SPV_NV_mesh_shader"
  1289. OpMemoryModel Logical GLSL450
  1290. OpEntryPoint MeshNV %foo "foo" %in
  1291. OpExecutionMode %foo LocalSize 1 1 1
  1292. OpDecorate %block Block
  1293. OpMemberDecorate %block 0 PerTaskNV
  1294. OpMemberDecorate %block 0 Offset 0
  1295. %void = OpTypeVoid
  1296. %int = OpTypeInt 32 0
  1297. %int_32 = OpConstant %int 32
  1298. %array = OpTypeArray %int %int_32
  1299. %block = OpTypeStruct %array
  1300. %ptr_input_block = OpTypePointer Input %block
  1301. %in = OpVariable %ptr_input_block Input
  1302. %void_fn = OpTypeFunction %void
  1303. %foo = OpFunction %void None %void_fn
  1304. %entry = OpLabel
  1305. OpReturn
  1306. OpFunctionEnd
  1307. )";
  1308. CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
  1309. EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
  1310. }
  1311. } // namespace
  1312. } // namespace val
  1313. } // namespace spvtools