analyze_live_input_test.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. // Copyright (c) 2022 The Khronos Group Inc.
  2. // Copyright (c) 2022 LunarG Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #include <unordered_set>
  16. #include "test/opt/pass_fixture.h"
  17. #include "test/opt/pass_utils.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace {
  21. using AnalyzeLiveInputTest = PassTest<::testing::Test>;
  22. TEST_F(AnalyzeLiveInputTest, FragMultipleLocations) {
  23. // Should report locations {2, 5}
  24. //
  25. // #version 450
  26. //
  27. // layout(location = 2) in Vertex
  28. // {
  29. // vec4 color0;
  30. // vec4 color1;
  31. // vec4 color2[3];
  32. // } iVert;
  33. //
  34. // layout(location = 0) out vec4 oFragColor;
  35. //
  36. // void main()
  37. // {
  38. // oFragColor = iVert.color0 + iVert.color2[1];
  39. // }
  40. const std::string text = R"(
  41. OpCapability Shader
  42. %1 = OpExtInstImport "GLSL.std.450"
  43. OpMemoryModel Logical GLSL450
  44. OpEntryPoint Fragment %main "main" %oFragColor %iVert
  45. OpExecutionMode %main OriginUpperLeft
  46. OpSource GLSL 450
  47. OpName %main "main"
  48. OpName %oFragColor "oFragColor"
  49. OpName %Vertex "Vertex"
  50. OpMemberName %Vertex 0 "color0"
  51. OpMemberName %Vertex 1 "color1"
  52. OpMemberName %Vertex 2 "color2"
  53. OpName %iVert "iVert"
  54. OpDecorate %oFragColor Location 0
  55. OpDecorate %Vertex Block
  56. OpDecorate %iVert Location 2
  57. %void = OpTypeVoid
  58. %3 = OpTypeFunction %void
  59. %float = OpTypeFloat 32
  60. %v4float = OpTypeVector %float 4
  61. %_ptr_Output_v4float = OpTypePointer Output %v4float
  62. %oFragColor = OpVariable %_ptr_Output_v4float Output
  63. %uint = OpTypeInt 32 0
  64. %uint_3 = OpConstant %uint 3
  65. %_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
  66. %Vertex = OpTypeStruct %v4float %v4float %_arr_v4float_uint_3
  67. %_ptr_Input_Vertex = OpTypePointer Input %Vertex
  68. %iVert = OpVariable %_ptr_Input_Vertex Input
  69. %int = OpTypeInt 32 1
  70. %int_0 = OpConstant %int 0
  71. %_ptr_Input_v4float = OpTypePointer Input %v4float
  72. %int_2 = OpConstant %int 2
  73. %int_1 = OpConstant %int 1
  74. %main = OpFunction %void None %3
  75. %5 = OpLabel
  76. %19 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
  77. %20 = OpLoad %v4float %19
  78. %23 = OpAccessChain %_ptr_Input_v4float %iVert %int_2 %int_1
  79. %24 = OpLoad %v4float %23
  80. %25 = OpFAdd %v4float %20 %24
  81. OpStore %oFragColor %25
  82. OpReturn
  83. OpFunctionEnd
  84. )";
  85. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  86. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  87. std::unordered_set<uint32_t> live_inputs;
  88. std::unordered_set<uint32_t> live_builtins;
  89. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  90. text, true, &live_inputs, &live_builtins);
  91. auto itr0 = live_inputs.find(0);
  92. auto itr1 = live_inputs.find(1);
  93. auto itr2 = live_inputs.find(2);
  94. auto itr3 = live_inputs.find(3);
  95. auto itr4 = live_inputs.find(4);
  96. auto itr5 = live_inputs.find(5);
  97. auto itr6 = live_inputs.find(6);
  98. // Expect live_inputs == {2, 5}
  99. EXPECT_TRUE(itr0 == live_inputs.end());
  100. EXPECT_TRUE(itr1 == live_inputs.end());
  101. EXPECT_TRUE(itr2 != live_inputs.end());
  102. EXPECT_TRUE(itr3 == live_inputs.end());
  103. EXPECT_TRUE(itr4 == live_inputs.end());
  104. EXPECT_TRUE(itr5 != live_inputs.end());
  105. EXPECT_TRUE(itr6 == live_inputs.end());
  106. }
  107. TEST_F(AnalyzeLiveInputTest, FragMatrix) {
  108. // Should report locations {2, 8, 9, 10, 11}
  109. //
  110. // #version 450
  111. //
  112. // uniform ui_name {
  113. // int i;
  114. // } ui_inst;
  115. //
  116. // layout(location = 2) in Vertex
  117. // {
  118. // vec4 color0;
  119. // vec4 color1;
  120. // mat4 color2;
  121. // mat4 color3;
  122. // mat4 color4;
  123. // } iVert;
  124. //
  125. // // Output variable for the color
  126. // layout(location = 0) out vec4 oFragColor;
  127. //
  128. // void main()
  129. // {
  130. // oFragColor = iVert.color0 + iVert.color3[ui_inst.i];
  131. // }
  132. const std::string text = R"(
  133. OpCapability Shader
  134. %1 = OpExtInstImport "GLSL.std.450"
  135. OpMemoryModel Logical GLSL450
  136. OpEntryPoint Fragment %main "main" %oFragColor %iVert %ui_inst
  137. OpExecutionMode %main OriginUpperLeft
  138. OpSource GLSL 450
  139. OpName %main "main"
  140. OpName %oFragColor "oFragColor"
  141. OpName %Vertex "Vertex"
  142. OpMemberName %Vertex 0 "color0"
  143. OpMemberName %Vertex 1 "color1"
  144. OpMemberName %Vertex 2 "color2"
  145. OpMemberName %Vertex 3 "color3"
  146. OpMemberName %Vertex 4 "color4"
  147. OpName %iVert "iVert"
  148. OpName %ui_name "ui_name"
  149. OpMemberName %ui_name 0 "i"
  150. OpName %ui_inst "ui_inst"
  151. OpDecorate %oFragColor Location 0
  152. OpDecorate %Vertex Block
  153. OpDecorate %iVert Location 2
  154. OpMemberDecorate %ui_name 0 Offset 0
  155. OpDecorate %ui_name Block
  156. OpDecorate %ui_inst DescriptorSet 0
  157. OpDecorate %ui_inst Binding 0
  158. %void = OpTypeVoid
  159. %3 = OpTypeFunction %void
  160. %float = OpTypeFloat 32
  161. %v4float = OpTypeVector %float 4
  162. %_ptr_Output_v4float = OpTypePointer Output %v4float
  163. %oFragColor = OpVariable %_ptr_Output_v4float Output
  164. %mat4v4float = OpTypeMatrix %v4float 4
  165. %Vertex = OpTypeStruct %v4float %v4float %mat4v4float %mat4v4float %mat4v4float
  166. %_ptr_Input_Vertex = OpTypePointer Input %Vertex
  167. %iVert = OpVariable %_ptr_Input_Vertex Input
  168. %int = OpTypeInt 32 1
  169. %int_0 = OpConstant %int 0
  170. %_ptr_Input_v4float = OpTypePointer Input %v4float
  171. %int_3 = OpConstant %int 3
  172. %ui_name = OpTypeStruct %int
  173. %_ptr_Uniform_ui_name = OpTypePointer Uniform %ui_name
  174. %ui_inst = OpVariable %_ptr_Uniform_ui_name Uniform
  175. %_ptr_Uniform_int = OpTypePointer Uniform %int
  176. %main = OpFunction %void None %3
  177. %5 = OpLabel
  178. %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
  179. %18 = OpLoad %v4float %17
  180. %24 = OpAccessChain %_ptr_Uniform_int %ui_inst %int_0
  181. %25 = OpLoad %int %24
  182. %26 = OpAccessChain %_ptr_Input_v4float %iVert %int_3 %25
  183. %27 = OpLoad %v4float %26
  184. %28 = OpFAdd %v4float %18 %27
  185. OpStore %oFragColor %28
  186. OpReturn
  187. OpFunctionEnd
  188. )";
  189. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  190. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  191. std::unordered_set<uint32_t> live_inputs;
  192. std::unordered_set<uint32_t> live_builtins;
  193. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  194. text, true, &live_inputs, &live_builtins);
  195. auto itr0 = live_inputs.find(0);
  196. auto itr1 = live_inputs.find(1);
  197. auto itr2 = live_inputs.find(2);
  198. auto itr3 = live_inputs.find(3);
  199. auto itr4 = live_inputs.find(4);
  200. auto itr5 = live_inputs.find(5);
  201. auto itr6 = live_inputs.find(6);
  202. auto itr7 = live_inputs.find(7);
  203. auto itr8 = live_inputs.find(8);
  204. auto itr9 = live_inputs.find(9);
  205. auto itr10 = live_inputs.find(10);
  206. auto itr11 = live_inputs.find(11);
  207. auto itr12 = live_inputs.find(12);
  208. auto itr13 = live_inputs.find(13);
  209. auto itr14 = live_inputs.find(14);
  210. auto itr15 = live_inputs.find(15);
  211. // Expect live_inputs == {2, 8, 9, 10, 11}
  212. EXPECT_TRUE(itr0 == live_inputs.end());
  213. EXPECT_TRUE(itr1 == live_inputs.end());
  214. EXPECT_TRUE(itr2 != live_inputs.end());
  215. EXPECT_TRUE(itr3 == live_inputs.end());
  216. EXPECT_TRUE(itr4 == live_inputs.end());
  217. EXPECT_TRUE(itr5 == live_inputs.end());
  218. EXPECT_TRUE(itr6 == live_inputs.end());
  219. EXPECT_TRUE(itr7 == live_inputs.end());
  220. EXPECT_TRUE(itr8 != live_inputs.end());
  221. EXPECT_TRUE(itr9 != live_inputs.end());
  222. EXPECT_TRUE(itr10 != live_inputs.end());
  223. EXPECT_TRUE(itr11 != live_inputs.end());
  224. EXPECT_TRUE(itr12 == live_inputs.end());
  225. EXPECT_TRUE(itr13 == live_inputs.end());
  226. EXPECT_TRUE(itr14 == live_inputs.end());
  227. EXPECT_TRUE(itr15 == live_inputs.end());
  228. }
  229. TEST_F(AnalyzeLiveInputTest, FragMemberLocs) {
  230. // Should report location {1}
  231. //
  232. // #version 450
  233. //
  234. // in Vertex
  235. // {
  236. // layout (location = 1) vec4 Cd;
  237. // layout (location = 0) vec2 uv;
  238. // } iVert;
  239. //
  240. // layout (location = 0) out vec4 fragColor;
  241. //
  242. // void main()
  243. // {
  244. // vec4 color = vec4(iVert.Cd);
  245. // fragColor = color;
  246. // }
  247. const std::string text = R"(
  248. OpCapability Shader
  249. %1 = OpExtInstImport "GLSL.std.450"
  250. OpMemoryModel Logical GLSL450
  251. OpEntryPoint Fragment %main "main" %iVert %fragColor
  252. OpExecutionMode %main OriginUpperLeft
  253. OpSource GLSL 450
  254. OpName %main "main"
  255. OpName %color "color"
  256. OpName %Vertex "Vertex"
  257. OpMemberName %Vertex 0 "Cd"
  258. OpMemberName %Vertex 1 "uv"
  259. OpName %iVert "iVert"
  260. OpName %fragColor "fragColor"
  261. OpMemberDecorate %Vertex 0 Location 1
  262. OpMemberDecorate %Vertex 1 Location 0
  263. OpDecorate %Vertex Block
  264. OpDecorate %fragColor Location 0
  265. OpDecorate %_struct_27 Block
  266. OpMemberDecorate %_struct_27 0 Location 1
  267. %void = OpTypeVoid
  268. %3 = OpTypeFunction %void
  269. %float = OpTypeFloat 32
  270. %v4float = OpTypeVector %float 4
  271. %_ptr_Function_v4float = OpTypePointer Function %v4float
  272. %v2float = OpTypeVector %float 2
  273. %Vertex = OpTypeStruct %v4float %v2float
  274. %_ptr_Input_Vertex = OpTypePointer Input %Vertex
  275. %int = OpTypeInt 32 1
  276. %int_0 = OpConstant %int 0
  277. %_ptr_Input_v4float = OpTypePointer Input %v4float
  278. %_ptr_Output_v4float = OpTypePointer Output %v4float
  279. %fragColor = OpVariable %_ptr_Output_v4float Output
  280. %_struct_27 = OpTypeStruct %v4float
  281. %_ptr_Input__struct_27 = OpTypePointer Input %_struct_27
  282. %iVert = OpVariable %_ptr_Input__struct_27 Input
  283. %main = OpFunction %void None %3
  284. %5 = OpLabel
  285. %color = OpVariable %_ptr_Function_v4float Function
  286. %17 = OpAccessChain %_ptr_Input_v4float %iVert %int_0
  287. %18 = OpLoad %v4float %17
  288. %19 = OpCompositeExtract %float %18 0
  289. %20 = OpCompositeExtract %float %18 1
  290. %21 = OpCompositeExtract %float %18 2
  291. %22 = OpCompositeExtract %float %18 3
  292. %23 = OpCompositeConstruct %v4float %19 %20 %21 %22
  293. OpStore %color %23
  294. %26 = OpLoad %v4float %color
  295. OpStore %fragColor %26
  296. OpReturn
  297. OpFunctionEnd
  298. )";
  299. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  300. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  301. std::unordered_set<uint32_t> live_inputs;
  302. std::unordered_set<uint32_t> live_builtins;
  303. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  304. text, true, &live_inputs, &live_builtins);
  305. auto itr0 = live_inputs.find(0);
  306. auto itr1 = live_inputs.find(1);
  307. // Expect live_inputs == {2, 5}
  308. EXPECT_TRUE(itr0 == live_inputs.end());
  309. EXPECT_TRUE(itr1 != live_inputs.end());
  310. }
  311. TEST_F(AnalyzeLiveInputTest, ArrayedInput) {
  312. // Tests handling of arrayed input seen in Tesc, Tese and Geom shaders.
  313. //
  314. // Should report location {1, 10}.
  315. //
  316. // #version 450
  317. //
  318. // layout (vertices = 4) out;
  319. //
  320. // layout (location = 1) in Vertex
  321. // {
  322. // vec4 p;
  323. // vec3 n;
  324. // vec4 f[100];
  325. // } iVert[];
  326. //
  327. // layout (location = 0) out vec4 position[4];
  328. //
  329. // void main()
  330. // {
  331. // vec4 pos = iVert[gl_InvocationID].p *
  332. // iVert[gl_InvocationID].f[7];
  333. // position[gl_InvocationID] = pos;
  334. // }
  335. const std::string text = R"(
  336. OpCapability Tessellation
  337. %1 = OpExtInstImport "GLSL.std.450"
  338. OpMemoryModel Logical GLSL450
  339. OpEntryPoint TessellationControl %main "main" %iVert %gl_InvocationID %position
  340. OpExecutionMode %main OutputVertices 4
  341. OpSource GLSL 450
  342. OpName %main "main"
  343. OpName %Vertex "Vertex"
  344. OpMemberName %Vertex 0 "p"
  345. OpMemberName %Vertex 1 "n"
  346. OpMemberName %Vertex 2 "f"
  347. OpName %iVert "iVert"
  348. OpName %gl_InvocationID "gl_InvocationID"
  349. OpName %position "position"
  350. OpDecorate %Vertex Block
  351. OpDecorate %iVert Location 1
  352. OpDecorate %gl_InvocationID BuiltIn InvocationId
  353. OpDecorate %position Location 0
  354. %void = OpTypeVoid
  355. %3 = OpTypeFunction %void
  356. %float = OpTypeFloat 32
  357. %v4float = OpTypeVector %float 4
  358. %v3float = OpTypeVector %float 3
  359. %uint = OpTypeInt 32 0
  360. %uint_100 = OpConstant %uint 100
  361. %_arr_v4float_uint_100 = OpTypeArray %v4float %uint_100
  362. %Vertex = OpTypeStruct %v4float %v3float %_arr_v4float_uint_100
  363. %uint_32 = OpConstant %uint 32
  364. %_arr_Vertex_uint_32 = OpTypeArray %Vertex %uint_32
  365. %_ptr_Input__arr_Vertex_uint_32 = OpTypePointer Input %_arr_Vertex_uint_32
  366. %iVert = OpVariable %_ptr_Input__arr_Vertex_uint_32 Input
  367. %int = OpTypeInt 32 1
  368. %_ptr_Input_int = OpTypePointer Input %int
  369. %gl_InvocationID = OpVariable %_ptr_Input_int Input
  370. %int_0 = OpConstant %int 0
  371. %_ptr_Input_v4float = OpTypePointer Input %v4float
  372. %int_2 = OpConstant %int 2
  373. %int_7 = OpConstant %int 7
  374. %uint_4 = OpConstant %uint 4
  375. %_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
  376. %_ptr_Output__arr_v4float_uint_4 = OpTypePointer Output %_arr_v4float_uint_4
  377. %position = OpVariable %_ptr_Output__arr_v4float_uint_4 Output
  378. %_ptr_Output_v4float = OpTypePointer Output %v4float
  379. %main = OpFunction %void None %3
  380. %5 = OpLabel
  381. %22 = OpLoad %int %gl_InvocationID
  382. %25 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_0
  383. %26 = OpLoad %v4float %25
  384. %30 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_2 %int_7
  385. %31 = OpLoad %v4float %30
  386. %32 = OpFMul %v4float %26 %31
  387. %40 = OpAccessChain %_ptr_Output_v4float %position %22
  388. OpStore %40 %32
  389. OpReturn
  390. OpFunctionEnd
  391. )";
  392. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  393. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  394. std::unordered_set<uint32_t> live_inputs;
  395. std::unordered_set<uint32_t> live_builtins;
  396. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  397. text, true, &live_inputs, &live_builtins);
  398. auto itr0 = live_inputs.find(0);
  399. auto itr1 = live_inputs.find(1);
  400. auto itr2 = live_inputs.find(2);
  401. auto itr3 = live_inputs.find(3);
  402. auto itr4 = live_inputs.find(4);
  403. auto itr5 = live_inputs.find(5);
  404. auto itr6 = live_inputs.find(6);
  405. auto itr7 = live_inputs.find(7);
  406. auto itr8 = live_inputs.find(8);
  407. auto itr9 = live_inputs.find(9);
  408. auto itr10 = live_inputs.find(10);
  409. auto itr11 = live_inputs.find(11);
  410. // Expect live_inputs == {1, 10}
  411. EXPECT_TRUE(itr0 == live_inputs.end());
  412. EXPECT_TRUE(itr1 != live_inputs.end());
  413. EXPECT_TRUE(itr2 == live_inputs.end());
  414. EXPECT_TRUE(itr3 == live_inputs.end());
  415. EXPECT_TRUE(itr4 == live_inputs.end());
  416. EXPECT_TRUE(itr5 == live_inputs.end());
  417. EXPECT_TRUE(itr6 == live_inputs.end());
  418. EXPECT_TRUE(itr7 == live_inputs.end());
  419. EXPECT_TRUE(itr8 == live_inputs.end());
  420. EXPECT_TRUE(itr9 == live_inputs.end());
  421. EXPECT_TRUE(itr10 != live_inputs.end());
  422. EXPECT_TRUE(itr11 == live_inputs.end());
  423. }
  424. TEST_F(AnalyzeLiveInputTest, ArrayedInputMemberLocs) {
  425. // Tests handling of member locs with arrayed input seen in Tesc, Tese
  426. // and Geom shaders.
  427. //
  428. // Should report location {1, 12}.
  429. //
  430. // #version 450
  431. //
  432. // layout (vertices = 4) out;
  433. //
  434. // in Vertex
  435. // {
  436. // layout (location = 1) vec4 p;
  437. // layout (location = 3) vec3 n;
  438. // layout (location = 5) vec4 f[100];
  439. // } iVert[];
  440. //
  441. // layout (location = 0) out vec4 position[4];
  442. //
  443. // void main()
  444. // {
  445. // vec4 pos = iVert[gl_InvocationID].p *
  446. // iVert[gl_InvocationID].f[7];
  447. // position[gl_InvocationID] = pos;
  448. // }
  449. const std::string text = R"(
  450. OpCapability Tessellation
  451. %1 = OpExtInstImport "GLSL.std.450"
  452. OpMemoryModel Logical GLSL450
  453. OpEntryPoint TessellationControl %main "main" %iVert %gl_InvocationID %position
  454. OpExecutionMode %main OutputVertices 4
  455. OpSource GLSL 450
  456. OpName %main "main"
  457. OpName %Vertex "Vertex"
  458. OpMemberName %Vertex 0 "p"
  459. OpMemberName %Vertex 1 "n"
  460. OpMemberName %Vertex 2 "f"
  461. OpName %iVert "iVert"
  462. OpName %gl_InvocationID "gl_InvocationID"
  463. OpName %position "position"
  464. OpMemberDecorate %Vertex 0 Location 1
  465. OpMemberDecorate %Vertex 1 Location 3
  466. OpMemberDecorate %Vertex 2 Location 5
  467. OpDecorate %Vertex Block
  468. OpDecorate %gl_InvocationID BuiltIn InvocationId
  469. OpDecorate %position Location 0
  470. %void = OpTypeVoid
  471. %3 = OpTypeFunction %void
  472. %float = OpTypeFloat 32
  473. %v4float = OpTypeVector %float 4
  474. %v3float = OpTypeVector %float 3
  475. %uint = OpTypeInt 32 0
  476. %uint_100 = OpConstant %uint 100
  477. %_arr_v4float_uint_100 = OpTypeArray %v4float %uint_100
  478. %Vertex = OpTypeStruct %v4float %v3float %_arr_v4float_uint_100
  479. %uint_32 = OpConstant %uint 32
  480. %_arr_Vertex_uint_32 = OpTypeArray %Vertex %uint_32
  481. %_ptr_Input__arr_Vertex_uint_32 = OpTypePointer Input %_arr_Vertex_uint_32
  482. %iVert = OpVariable %_ptr_Input__arr_Vertex_uint_32 Input
  483. %int = OpTypeInt 32 1
  484. %_ptr_Input_int = OpTypePointer Input %int
  485. %gl_InvocationID = OpVariable %_ptr_Input_int Input
  486. %int_0 = OpConstant %int 0
  487. %_ptr_Input_v4float = OpTypePointer Input %v4float
  488. %int_2 = OpConstant %int 2
  489. %int_7 = OpConstant %int 7
  490. %uint_4 = OpConstant %uint 4
  491. %_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
  492. %_ptr_Output__arr_v4float_uint_4 = OpTypePointer Output %_arr_v4float_uint_4
  493. %position = OpVariable %_ptr_Output__arr_v4float_uint_4 Output
  494. %_ptr_Output_v4float = OpTypePointer Output %v4float
  495. %main = OpFunction %void None %3
  496. %5 = OpLabel
  497. %22 = OpLoad %int %gl_InvocationID
  498. %25 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_0
  499. %26 = OpLoad %v4float %25
  500. %30 = OpAccessChain %_ptr_Input_v4float %iVert %22 %int_2 %int_7
  501. %31 = OpLoad %v4float %30
  502. %32 = OpFMul %v4float %26 %31
  503. %40 = OpAccessChain %_ptr_Output_v4float %position %22
  504. OpStore %40 %32
  505. OpReturn
  506. OpFunctionEnd
  507. )";
  508. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  509. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  510. std::unordered_set<uint32_t> live_inputs;
  511. std::unordered_set<uint32_t> live_builtins;
  512. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  513. text, true, &live_inputs, &live_builtins);
  514. auto itr0 = live_inputs.find(0);
  515. auto itr1 = live_inputs.find(1);
  516. auto itr2 = live_inputs.find(2);
  517. auto itr3 = live_inputs.find(3);
  518. auto itr4 = live_inputs.find(4);
  519. auto itr5 = live_inputs.find(5);
  520. auto itr6 = live_inputs.find(6);
  521. auto itr7 = live_inputs.find(7);
  522. auto itr8 = live_inputs.find(8);
  523. auto itr9 = live_inputs.find(9);
  524. auto itr10 = live_inputs.find(10);
  525. auto itr11 = live_inputs.find(11);
  526. auto itr12 = live_inputs.find(12);
  527. auto itr13 = live_inputs.find(13);
  528. // Expect live_inputs == {1, 12}
  529. EXPECT_TRUE(itr0 == live_inputs.end());
  530. EXPECT_TRUE(itr1 != live_inputs.end());
  531. EXPECT_TRUE(itr2 == live_inputs.end());
  532. EXPECT_TRUE(itr3 == live_inputs.end());
  533. EXPECT_TRUE(itr4 == live_inputs.end());
  534. EXPECT_TRUE(itr5 == live_inputs.end());
  535. EXPECT_TRUE(itr6 == live_inputs.end());
  536. EXPECT_TRUE(itr7 == live_inputs.end());
  537. EXPECT_TRUE(itr8 == live_inputs.end());
  538. EXPECT_TRUE(itr9 == live_inputs.end());
  539. EXPECT_TRUE(itr10 == live_inputs.end());
  540. EXPECT_TRUE(itr11 == live_inputs.end());
  541. EXPECT_TRUE(itr12 != live_inputs.end());
  542. EXPECT_TRUE(itr13 == live_inputs.end());
  543. }
  544. TEST_F(AnalyzeLiveInputTest, Builtins) {
  545. // Tests handling of builtin input seen in Tesc, Tese and Geom shaders.
  546. //
  547. // Should report builtin gl_PointSize only.
  548. //
  549. // #version 460
  550. //
  551. // layout(triangle_strip, max_vertices = 3) out;
  552. // layout(triangles) in;
  553. //
  554. // void main()
  555. // {
  556. // for (int i = 0; i < 3; i++)
  557. // {
  558. // gl_Position = gl_in[i].gl_Position;
  559. // gl_PointSize = gl_in[i].gl_PointSize;
  560. //
  561. // EmitVertex();
  562. // }
  563. //
  564. // EndPrimitive();
  565. // }
  566. const std::string text = R"(
  567. OpCapability Geometry
  568. OpCapability GeometryPointSize
  569. %1 = OpExtInstImport "GLSL.std.450"
  570. OpMemoryModel Logical GLSL450
  571. OpEntryPoint Geometry %main "main" %_ %gl_in
  572. OpExecutionMode %main Triangles
  573. OpExecutionMode %main Invocations 1
  574. OpExecutionMode %main OutputTriangleStrip
  575. OpExecutionMode %main OutputVertices 3
  576. OpSource GLSL 460
  577. OpName %main "main"
  578. OpName %i "i"
  579. OpName %gl_PerVertex "gl_PerVertex"
  580. OpMemberName %gl_PerVertex 0 "gl_Position"
  581. OpMemberName %gl_PerVertex 1 "gl_PointSize"
  582. OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
  583. OpMemberName %gl_PerVertex 3 "gl_CullDistance"
  584. OpName %_ ""
  585. OpName %gl_PerVertex_0 "gl_PerVertex"
  586. OpMemberName %gl_PerVertex_0 0 "gl_Position"
  587. OpMemberName %gl_PerVertex_0 1 "gl_PointSize"
  588. OpMemberName %gl_PerVertex_0 2 "gl_ClipDistance"
  589. OpMemberName %gl_PerVertex_0 3 "gl_CullDistance"
  590. OpName %gl_in "gl_in"
  591. OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
  592. OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
  593. OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
  594. OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
  595. OpDecorate %gl_PerVertex Block
  596. OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
  597. OpMemberDecorate %gl_PerVertex_0 1 BuiltIn PointSize
  598. OpDecorate %gl_PerVertex_0 Block
  599. %void = OpTypeVoid
  600. %3 = OpTypeFunction %void
  601. %int = OpTypeInt 32 1
  602. %_ptr_Function_int = OpTypePointer Function %int
  603. %int_0 = OpConstant %int 0
  604. %int_3 = OpConstant %int 3
  605. %bool = OpTypeBool
  606. %float = OpTypeFloat 32
  607. %v4float = OpTypeVector %float 4
  608. %uint = OpTypeInt 32 0
  609. %uint_1 = OpConstant %uint 1
  610. %_arr_float_uint_1 = OpTypeArray %float %uint_1
  611. %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
  612. %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
  613. %_ = OpVariable %_ptr_Output_gl_PerVertex Output
  614. %gl_PerVertex_0 = OpTypeStruct %v4float %float
  615. %uint_3 = OpConstant %uint 3
  616. %_arr_gl_PerVertex_0_uint_3 = OpTypeArray %gl_PerVertex_0 %uint_3
  617. %_ptr_Input__arr_gl_PerVertex_0_uint_3 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_3
  618. %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_3 Input
  619. %_ptr_Input_v4float = OpTypePointer Input %v4float
  620. %_ptr_Output_v4float = OpTypePointer Output %v4float
  621. %int_1 = OpConstant %int 1
  622. %_ptr_Input_float = OpTypePointer Input %float
  623. %_ptr_Output_float = OpTypePointer Output %float
  624. %main = OpFunction %void None %3
  625. %5 = OpLabel
  626. %i = OpVariable %_ptr_Function_int Function
  627. OpStore %i %int_0
  628. OpBranch %10
  629. %10 = OpLabel
  630. OpLoopMerge %12 %13 None
  631. OpBranch %14
  632. %14 = OpLabel
  633. %15 = OpLoad %int %i
  634. %18 = OpSLessThan %bool %15 %int_3
  635. OpBranchConditional %18 %11 %12
  636. %11 = OpLabel
  637. %32 = OpLoad %int %i
  638. %34 = OpAccessChain %_ptr_Input_v4float %gl_in %32 %int_0
  639. %35 = OpLoad %v4float %34
  640. %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
  641. OpStore %37 %35
  642. %39 = OpLoad %int %i
  643. %41 = OpAccessChain %_ptr_Input_float %gl_in %39 %int_1
  644. %42 = OpLoad %float %41
  645. %44 = OpAccessChain %_ptr_Output_float %_ %int_1
  646. OpStore %44 %42
  647. OpEmitVertex
  648. OpBranch %13
  649. %13 = OpLabel
  650. %45 = OpLoad %int %i
  651. %46 = OpIAdd %int %45 %int_1
  652. OpStore %i %46
  653. OpBranch %10
  654. %12 = OpLabel
  655. OpEndPrimitive
  656. OpReturn
  657. OpFunctionEnd
  658. )";
  659. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  660. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  661. std::unordered_set<uint32_t> live_inputs;
  662. std::unordered_set<uint32_t> live_builtins;
  663. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  664. text, true, &live_inputs, &live_builtins);
  665. auto itr0 = live_builtins.find((uint32_t)spv::BuiltIn::PointSize);
  666. auto itr1 = live_builtins.find((uint32_t)spv::BuiltIn::ClipDistance);
  667. auto itr2 = live_builtins.find((uint32_t)spv::BuiltIn::CullDistance);
  668. // Expect live_builtins == { spv::BuiltIn::PointSize }
  669. EXPECT_TRUE(itr0 != live_builtins.end());
  670. EXPECT_TRUE(itr1 == live_builtins.end());
  671. EXPECT_TRUE(itr2 == live_builtins.end());
  672. }
  673. TEST_F(AnalyzeLiveInputTest, ArrayedInputPatchLocs) {
  674. // Tests handling of locs with arrayed input patch seen in Tese
  675. //
  676. // Should report location {3}.
  677. //
  678. // #version 450 core
  679. //
  680. // layout(triangles, ccw) in;
  681. //
  682. // layout(fractional_odd_spacing) in;
  683. //
  684. // layout(point_mode) in;
  685. //
  686. // layout(location=2) patch in float patchIn1[2];
  687. //
  688. // void main()
  689. // {
  690. // vec4 p = gl_in[1].gl_Position;
  691. // gl_Position = p * patchIn1[1];
  692. // }
  693. const std::string text = R"(
  694. OpCapability Tessellation
  695. %1 = OpExtInstImport "GLSL.std.450"
  696. OpMemoryModel Logical GLSL450
  697. OpEntryPoint TessellationEvaluation %main "main" %gl_in %_ %patchIn1
  698. OpExecutionMode %main Triangles
  699. OpExecutionMode %main SpacingFractionalOdd
  700. OpExecutionMode %main VertexOrderCcw
  701. OpExecutionMode %main PointMode
  702. OpSource GLSL 450
  703. OpName %main "main"
  704. OpName %p "p"
  705. OpName %gl_PerVertex "gl_PerVertex"
  706. OpMemberName %gl_PerVertex 0 "gl_Position"
  707. OpName %gl_in "gl_in"
  708. OpName %gl_PerVertex_0 "gl_PerVertex"
  709. OpMemberName %gl_PerVertex_0 0 "gl_Position"
  710. OpName %_ ""
  711. OpName %patchIn1 "patchIn1"
  712. OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
  713. OpDecorate %gl_PerVertex Block
  714. OpMemberDecorate %gl_PerVertex_0 0 BuiltIn Position
  715. OpDecorate %gl_PerVertex_0 Block
  716. OpDecorate %patchIn1 Patch
  717. OpDecorate %patchIn1 Location 2
  718. %void = OpTypeVoid
  719. %3 = OpTypeFunction %void
  720. %float = OpTypeFloat 32
  721. %v4float = OpTypeVector %float 4
  722. %_ptr_Function_v4float = OpTypePointer Function %v4float
  723. %uint = OpTypeInt 32 0
  724. %uint_1 = OpConstant %uint 1
  725. %_arr_float_uint_1 = OpTypeArray %float %uint_1
  726. %gl_PerVertex = OpTypeStruct %v4float
  727. %uint_32 = OpConstant %uint 32
  728. %_arr_gl_PerVertex_uint_32 = OpTypeArray %gl_PerVertex %uint_32
  729. %_ptr_Input__arr_gl_PerVertex_uint_32 = OpTypePointer Input %_arr_gl_PerVertex_uint_32
  730. %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_uint_32 Input
  731. %int = OpTypeInt 32 1
  732. %int_1 = OpConstant %int 1
  733. %int_0 = OpConstant %int 0
  734. %_ptr_Input_v4float = OpTypePointer Input %v4float
  735. %gl_PerVertex_0 = OpTypeStruct %v4float
  736. %_ptr_Output_gl_PerVertex_0 = OpTypePointer Output %gl_PerVertex_0
  737. %_ = OpVariable %_ptr_Output_gl_PerVertex_0 Output
  738. %uint_2 = OpConstant %uint 2
  739. %_arr_float_uint_2 = OpTypeArray %float %uint_2
  740. %_ptr_Input__arr_float_uint_2 = OpTypePointer Input %_arr_float_uint_2
  741. %patchIn1 = OpVariable %_ptr_Input__arr_float_uint_2 Input
  742. %_ptr_Input_float = OpTypePointer Input %float
  743. %_ptr_Output_v4float = OpTypePointer Output %v4float
  744. %main = OpFunction %void None %3
  745. %5 = OpLabel
  746. %p = OpVariable %_ptr_Function_v4float Function
  747. %22 = OpAccessChain %_ptr_Input_v4float %gl_in %int_1 %int_0
  748. %23 = OpLoad %v4float %22
  749. OpStore %p %23
  750. %27 = OpLoad %v4float %p
  751. %33 = OpAccessChain %_ptr_Input_float %patchIn1 %int_1
  752. %34 = OpLoad %float %33
  753. %35 = OpVectorTimesScalar %v4float %27 %34
  754. %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
  755. OpStore %37 %35
  756. OpReturn
  757. OpFunctionEnd
  758. )";
  759. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  760. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  761. std::unordered_set<uint32_t> live_inputs;
  762. std::unordered_set<uint32_t> live_builtins;
  763. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  764. text, true, &live_inputs, &live_builtins);
  765. auto itr0 = live_inputs.find(0);
  766. auto itr1 = live_inputs.find(1);
  767. auto itr2 = live_inputs.find(2);
  768. auto itr3 = live_inputs.find(3);
  769. // Expect live_inputs == {3}
  770. EXPECT_TRUE(itr0 == live_inputs.end());
  771. EXPECT_TRUE(itr1 == live_inputs.end());
  772. EXPECT_TRUE(itr2 == live_inputs.end());
  773. EXPECT_TRUE(itr3 != live_inputs.end());
  774. }
  775. TEST_F(AnalyzeLiveInputTest, FragMultipleLocationsF16) {
  776. // Should report locations {2, 5}
  777. //
  778. // #version 450
  779. //
  780. // layout(location = 2) in Vertex
  781. // {
  782. // f16vec4 color0;
  783. // f16vec4 color1;
  784. // f16vec4 color2[3];
  785. // } iVert;
  786. //
  787. // layout(location = 0) out f16vec4 oFragColor;
  788. //
  789. // void main()
  790. // {
  791. // oFragColor = iVert.color0 + iVert.color2[1];
  792. // }
  793. const std::string text = R"(
  794. OpCapability Shader
  795. OpCapability Float16
  796. OpCapability StorageInputOutput16
  797. %1 = OpExtInstImport "GLSL.std.450"
  798. OpMemoryModel Logical GLSL450
  799. OpEntryPoint Fragment %main "main" %oFragColor %iVert
  800. OpExecutionMode %main OriginUpperLeft
  801. OpSource GLSL 450
  802. OpName %main "main"
  803. OpName %oFragColor "oFragColor"
  804. OpName %Vertex "Vertex"
  805. OpMemberName %Vertex 0 "color0"
  806. OpMemberName %Vertex 1 "color1"
  807. OpMemberName %Vertex 2 "color2"
  808. OpName %iVert "iVert"
  809. OpDecorate %oFragColor Location 0
  810. OpDecorate %Vertex Block
  811. OpDecorate %iVert Location 2
  812. %void = OpTypeVoid
  813. %3 = OpTypeFunction %void
  814. %half = OpTypeFloat 16
  815. %v4half = OpTypeVector %half 4
  816. %_ptr_Output_v4half = OpTypePointer Output %v4half
  817. %oFragColor = OpVariable %_ptr_Output_v4half Output
  818. %uint = OpTypeInt 32 0
  819. %uint_3 = OpConstant %uint 3
  820. %_arr_v4half_uint_3 = OpTypeArray %v4half %uint_3
  821. %Vertex = OpTypeStruct %v4half %v4half %_arr_v4half_uint_3
  822. %_ptr_Input_Vertex = OpTypePointer Input %Vertex
  823. %iVert = OpVariable %_ptr_Input_Vertex Input
  824. %int = OpTypeInt 32 1
  825. %int_0 = OpConstant %int 0
  826. %_ptr_Input_v4half = OpTypePointer Input %v4half
  827. %int_2 = OpConstant %int 2
  828. %int_1 = OpConstant %int 1
  829. %main = OpFunction %void None %3
  830. %5 = OpLabel
  831. %19 = OpAccessChain %_ptr_Input_v4half %iVert %int_0
  832. %20 = OpLoad %v4half %19
  833. %23 = OpAccessChain %_ptr_Input_v4half %iVert %int_2 %int_1
  834. %24 = OpLoad %v4half %23
  835. %25 = OpFAdd %v4half %20 %24
  836. OpStore %oFragColor %25
  837. OpReturn
  838. OpFunctionEnd
  839. )";
  840. SetTargetEnv(SPV_ENV_VULKAN_1_3);
  841. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  842. std::unordered_set<uint32_t> live_inputs;
  843. std::unordered_set<uint32_t> live_builtins;
  844. auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
  845. text, true, &live_inputs, &live_builtins);
  846. auto itr0 = live_inputs.find(0);
  847. auto itr1 = live_inputs.find(1);
  848. auto itr2 = live_inputs.find(2);
  849. auto itr3 = live_inputs.find(3);
  850. auto itr4 = live_inputs.find(4);
  851. auto itr5 = live_inputs.find(5);
  852. auto itr6 = live_inputs.find(6);
  853. // Expect live_inputs == {2, 5}
  854. EXPECT_TRUE(itr0 == live_inputs.end());
  855. EXPECT_TRUE(itr1 == live_inputs.end());
  856. EXPECT_TRUE(itr2 != live_inputs.end());
  857. EXPECT_TRUE(itr3 == live_inputs.end());
  858. EXPECT_TRUE(itr4 == live_inputs.end());
  859. EXPECT_TRUE(itr5 != live_inputs.end());
  860. EXPECT_TRUE(itr6 == live_inputs.end());
  861. }
  862. } // namespace
  863. } // namespace opt
  864. } // namespace spvtools