local_access_chain_convert_test.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412
  1. // Copyright (c) 2017 Valve Corporation
  2. // Copyright (c) 2017 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 <string>
  16. #include "test/opt/pass_fixture.h"
  17. #include "test/opt/pass_utils.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace {
  21. using LocalAccessChainConvertTest = PassTest<::testing::Test>;
  22. TEST_F(LocalAccessChainConvertTest, StructOfVecsOfFloatConverted) {
  23. // #version 140
  24. //
  25. // in vec4 BaseColor;
  26. //
  27. // struct S_t {
  28. // vec4 v0;
  29. // vec4 v1;
  30. // };
  31. //
  32. // void main()
  33. // {
  34. // S_t s0;
  35. // s0.v1 = BaseColor;
  36. // gl_FragColor = s0.v1;
  37. // }
  38. const std::string predefs_before =
  39. R"(OpCapability Shader
  40. %1 = OpExtInstImport "GLSL.std.450"
  41. OpMemoryModel Logical GLSL450
  42. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  43. OpExecutionMode %main OriginUpperLeft
  44. OpSource GLSL 140
  45. OpName %main "main"
  46. OpName %S_t "S_t"
  47. OpMemberName %S_t 0 "v0"
  48. OpMemberName %S_t 1 "v1"
  49. OpName %s0 "s0"
  50. OpName %BaseColor "BaseColor"
  51. OpName %gl_FragColor "gl_FragColor"
  52. %void = OpTypeVoid
  53. %8 = OpTypeFunction %void
  54. %float = OpTypeFloat 32
  55. %v4float = OpTypeVector %float 4
  56. %S_t = OpTypeStruct %v4float %v4float
  57. %_ptr_Function_S_t = OpTypePointer Function %S_t
  58. %int = OpTypeInt 32 1
  59. %int_1 = OpConstant %int 1
  60. %_ptr_Input_v4float = OpTypePointer Input %v4float
  61. %BaseColor = OpVariable %_ptr_Input_v4float Input
  62. %_ptr_Function_v4float = OpTypePointer Function %v4float
  63. %_ptr_Output_v4float = OpTypePointer Output %v4float
  64. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  65. )";
  66. const std::string before =
  67. R"(
  68. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  69. ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
  70. ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
  71. ; CHECK: OpStore %s0 [[ex1]]
  72. ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
  73. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
  74. ; CHECK: OpStore %gl_FragColor [[ex2]]
  75. %main = OpFunction %void None %8
  76. %17 = OpLabel
  77. %s0 = OpVariable %_ptr_Function_S_t Function
  78. %18 = OpLoad %v4float %BaseColor
  79. %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  80. OpStore %19 %18
  81. %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  82. %21 = OpLoad %v4float %20
  83. OpStore %gl_FragColor %21
  84. OpReturn
  85. OpFunctionEnd
  86. )";
  87. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  88. true);
  89. }
  90. TEST_F(LocalAccessChainConvertTest, DebugScopeAndLineInfoForNewInstructions) {
  91. // #version 140
  92. //
  93. // in vec4 BaseColor;
  94. //
  95. // struct S_t {
  96. // vec4 v0;
  97. // vec4 v1;
  98. // };
  99. //
  100. // void main()
  101. // {
  102. // S_t s0;
  103. // s0.v1 = BaseColor;
  104. // gl_FragColor = s0.v1;
  105. // }
  106. const std::string predefs_before =
  107. R"(OpCapability Shader
  108. %1 = OpExtInstImport "GLSL.std.450"
  109. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  110. OpMemoryModel Logical GLSL450
  111. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  112. OpExecutionMode %main OriginUpperLeft
  113. OpSource GLSL 140
  114. OpName %main "main"
  115. OpName %S_t "S_t"
  116. OpMemberName %S_t 0 "v0"
  117. OpMemberName %S_t 1 "v1"
  118. OpName %s0 "s0"
  119. OpName %BaseColor "BaseColor"
  120. OpName %gl_FragColor "gl_FragColor"
  121. %5 = OpString "ps.hlsl"
  122. %6 = OpString "float"
  123. %var_name = OpString "s0"
  124. %main_name = OpString "main"
  125. %void = OpTypeVoid
  126. %8 = OpTypeFunction %void
  127. %float = OpTypeFloat 32
  128. %v4float = OpTypeVector %float 4
  129. %S_t = OpTypeStruct %v4float %v4float
  130. %_ptr_Function_S_t = OpTypePointer Function %S_t
  131. %int = OpTypeInt 32 1
  132. %int_1 = OpConstant %int 1
  133. %int_32 = OpConstant %int 32
  134. %_ptr_Input_v4float = OpTypePointer Input %v4float
  135. %BaseColor = OpVariable %_ptr_Input_v4float Input
  136. %_ptr_Function_v4float = OpTypePointer Function %v4float
  137. %_ptr_Output_v4float = OpTypePointer Output %v4float
  138. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  139. %20 = OpExtInst %void %ext DebugSource %5
  140. %21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
  141. %22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
  142. %23 = OpExtInst %void %ext DebugTypeVector %22 4
  143. %24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
  144. %dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
  145. %25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
  146. )";
  147. const std::string before =
  148. R"(
  149. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  150. ; CHECK: OpLine {{%\w+}} 1 0
  151. ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
  152. ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
  153. ; CHECK: OpStore %s0 [[ex1]]
  154. ; CHECK: OpLine {{%\w+}} 3 0
  155. ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
  156. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
  157. ; CHECK: OpLine {{%\w+}} 4 0
  158. ; CHECK: OpStore %gl_FragColor [[ex2]]
  159. %main = OpFunction %void None %8
  160. %17 = OpLabel
  161. %26 = OpExtInst %void %ext DebugScope %dbg_main
  162. %s0 = OpVariable %_ptr_Function_S_t Function
  163. %18 = OpLoad %v4float %BaseColor
  164. OpLine %5 0 0
  165. %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  166. OpLine %5 1 0
  167. OpStore %19 %18
  168. OpLine %5 2 0
  169. %27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  170. OpLine %5 3 0
  171. %28 = OpLoad %v4float %27
  172. OpLine %5 4 0
  173. OpStore %gl_FragColor %28
  174. OpReturn
  175. OpFunctionEnd
  176. )";
  177. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  178. true);
  179. }
  180. TEST_F(LocalAccessChainConvertTest, TestTargetsReferencedByDebugValue) {
  181. // #version 140
  182. //
  183. // in vec4 BaseColor;
  184. //
  185. // struct S_t {
  186. // vec4 v0;
  187. // vec4 v1;
  188. // };
  189. //
  190. // void main()
  191. // {
  192. // S_t s0;
  193. // s0.v1 = BaseColor;
  194. // gl_FragColor = s0.v1;
  195. // }
  196. const std::string predefs_before =
  197. R"(OpCapability Shader
  198. %1 = OpExtInstImport "GLSL.std.450"
  199. %ext = OpExtInstImport "OpenCL.DebugInfo.100"
  200. OpMemoryModel Logical GLSL450
  201. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  202. OpExecutionMode %main OriginUpperLeft
  203. OpSource GLSL 140
  204. OpName %main "main"
  205. OpName %S_t "S_t"
  206. OpMemberName %S_t 0 "v0"
  207. OpMemberName %S_t 1 "v1"
  208. OpName %s0 "s0"
  209. OpName %BaseColor "BaseColor"
  210. OpName %gl_FragColor "gl_FragColor"
  211. %5 = OpString "ps.hlsl"
  212. %6 = OpString "float"
  213. %var_name = OpString "s0"
  214. %main_name = OpString "main"
  215. %void = OpTypeVoid
  216. %8 = OpTypeFunction %void
  217. %float = OpTypeFloat 32
  218. %v4float = OpTypeVector %float 4
  219. %S_t = OpTypeStruct %v4float %v4float
  220. %_ptr_Function_S_t = OpTypePointer Function %S_t
  221. %int = OpTypeInt 32 1
  222. %int_1 = OpConstant %int 1
  223. %int_32 = OpConstant %int 32
  224. %_ptr_Input_v4float = OpTypePointer Input %v4float
  225. %BaseColor = OpVariable %_ptr_Input_v4float Input
  226. %_ptr_Function_v4float = OpTypePointer Function %v4float
  227. %_ptr_Output_v4float = OpTypePointer Output %v4float
  228. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  229. %deref = OpExtInst %void %ext DebugOperation Deref
  230. %deref_expr = OpExtInst %void %ext DebugExpression %deref
  231. %null_expr = OpExtInst %void %ext DebugExpression
  232. %20 = OpExtInst %void %ext DebugSource %5
  233. %21 = OpExtInst %void %ext DebugCompilationUnit 1 4 %20 HLSL
  234. %22 = OpExtInst %void %ext DebugTypeBasic %6 %int_32 Float
  235. %23 = OpExtInst %void %ext DebugTypeVector %22 4
  236. %24 = OpExtInst %void %ext DebugTypeFunction FlagIsProtected|FlagIsPrivate %23
  237. %dbg_main = OpExtInst %void %ext DebugFunction %main_name %24 %20 4 1 %21 %main_name FlagIsProtected|FlagIsPrivate 4 %main
  238. %25 = OpExtInst %void %ext DebugLocalVariable %var_name %23 %20 0 0 %dbg_main FlagIsLocal
  239. )";
  240. const std::string before =
  241. R"(
  242. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  243. ; CHECK: OpLine {{%\w+}} 0 0
  244. ; CHECK: [[s0_1_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  245. ; CHECK: DebugValue [[dbg_s0:%\w+]] [[s0_1_ptr]]
  246. ; CHECK: OpLine {{%\w+}} 1 0
  247. ; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
  248. ; CHECK: [[comp:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[s0]] 1
  249. ; CHECK: OpStore %s0 [[comp]]
  250. ; CHECK: OpLine {{%\w+}} 2 0
  251. ; CHECK: [[s0_2_ptr:%\w+]] = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  252. ; CHECK: OpLine {{%\w+}} 3 0
  253. ; CHECK: [[s0:%\w+]] = OpLoad %S_t %s0
  254. ; CHECK: [[s0_2_val:%\w+]] = OpCompositeExtract %v4float [[s0]] 1
  255. ; CHECK: DebugValue [[dbg_s0]] [[s0_2_val]]
  256. ; CHECK: OpLine {{%\w+}} 4 0
  257. ; CHECK: OpStore %gl_FragColor [[s0_2_val]]
  258. %main = OpFunction %void None %8
  259. %17 = OpLabel
  260. %26 = OpExtInst %void %ext DebugScope %dbg_main
  261. %s0 = OpVariable %_ptr_Function_S_t Function
  262. %18 = OpLoad %v4float %BaseColor
  263. OpLine %5 0 0
  264. %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  265. %29 = OpExtInst %void %ext DebugValue %25 %19 %deref_expr %int_1
  266. OpLine %5 1 0
  267. OpStore %19 %18
  268. OpLine %5 2 0
  269. %27 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  270. OpLine %5 3 0
  271. %28 = OpLoad %v4float %27
  272. %30 = OpExtInst %void %ext DebugValue %25 %28 %null_expr %int_1
  273. OpLine %5 4 0
  274. OpStore %gl_FragColor %28
  275. OpReturn
  276. OpFunctionEnd
  277. )";
  278. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  279. true);
  280. }
  281. TEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) {
  282. // #version 140
  283. //
  284. // in vec4 BaseColor;
  285. //
  286. // struct S_t {
  287. // vec4 v0;
  288. // vec4 v1;
  289. // };
  290. //
  291. // void main()
  292. // {
  293. // S_t s0;
  294. // s0.v1 = BaseColor;
  295. // gl_FragColor = s0.v1;
  296. // }
  297. const std::string predefs_before =
  298. R"(OpCapability Shader
  299. %1 = OpExtInstImport "GLSL.std.450"
  300. OpMemoryModel Logical GLSL450
  301. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  302. OpExecutionMode %main OriginUpperLeft
  303. OpSource GLSL 140
  304. OpName %main "main"
  305. OpName %S_t "S_t"
  306. OpMemberName %S_t 0 "v0"
  307. OpMemberName %S_t 1 "v1"
  308. OpName %s0 "s0"
  309. OpName %BaseColor "BaseColor"
  310. OpName %gl_FragColor "gl_FragColor"
  311. %void = OpTypeVoid
  312. %8 = OpTypeFunction %void
  313. %float = OpTypeFloat 32
  314. %v4float = OpTypeVector %float 4
  315. %S_t = OpTypeStruct %v4float %v4float
  316. %_ptr_Function_S_t = OpTypePointer Function %S_t
  317. %int = OpTypeInt 32 1
  318. %int_1 = OpConstant %int 1
  319. %_ptr_Input_v4float = OpTypePointer Input %v4float
  320. %BaseColor = OpVariable %_ptr_Input_v4float Input
  321. %_ptr_Function_v4float = OpTypePointer Function %v4float
  322. %_ptr_Output_v4float = OpTypePointer Output %v4float
  323. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  324. )";
  325. const std::string before =
  326. R"(
  327. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  328. ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
  329. ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
  330. ; CHECK: OpStore %s0 [[ex1]]
  331. ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
  332. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
  333. ; CHECK: OpStore %gl_FragColor [[ex2]]
  334. %main = OpFunction %void None %8
  335. %17 = OpLabel
  336. %s0 = OpVariable %_ptr_Function_S_t Function
  337. %18 = OpLoad %v4float %BaseColor
  338. %19 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1
  339. OpStore %19 %18
  340. %20 = OpInBoundsAccessChain %_ptr_Function_v4float %s0 %int_1
  341. %21 = OpLoad %v4float %20
  342. OpStore %gl_FragColor %21
  343. OpReturn
  344. OpFunctionEnd
  345. )";
  346. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  347. true);
  348. }
  349. TEST_F(LocalAccessChainConvertTest, TwoUsesofSingleChainConverted) {
  350. // #version 140
  351. //
  352. // in vec4 BaseColor;
  353. //
  354. // struct S_t {
  355. // vec4 v0;
  356. // vec4 v1;
  357. // };
  358. //
  359. // void main()
  360. // {
  361. // S_t s0;
  362. // s0.v1 = BaseColor;
  363. // gl_FragColor = s0.v1;
  364. // }
  365. const std::string predefs_before =
  366. R"(OpCapability Shader
  367. %1 = OpExtInstImport "GLSL.std.450"
  368. OpMemoryModel Logical GLSL450
  369. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  370. OpExecutionMode %main OriginUpperLeft
  371. OpSource GLSL 140
  372. OpName %main "main"
  373. OpName %S_t "S_t"
  374. OpMemberName %S_t 0 "v0"
  375. OpMemberName %S_t 1 "v1"
  376. OpName %s0 "s0"
  377. OpName %BaseColor "BaseColor"
  378. OpName %gl_FragColor "gl_FragColor"
  379. %void = OpTypeVoid
  380. %8 = OpTypeFunction %void
  381. %float = OpTypeFloat 32
  382. %v4float = OpTypeVector %float 4
  383. %S_t = OpTypeStruct %v4float %v4float
  384. %_ptr_Function_S_t = OpTypePointer Function %S_t
  385. %int = OpTypeInt 32 1
  386. %int_1 = OpConstant %int 1
  387. %_ptr_Input_v4float = OpTypePointer Input %v4float
  388. %BaseColor = OpVariable %_ptr_Input_v4float Input
  389. %_ptr_Function_v4float = OpTypePointer Function %v4float
  390. %_ptr_Output_v4float = OpTypePointer Output %v4float
  391. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  392. )";
  393. const std::string before =
  394. R"(
  395. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  396. ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
  397. ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
  398. ; CHECK: OpStore %s0 [[ex1]]
  399. ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
  400. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
  401. ; CHECK: OpStore %gl_FragColor [[ex2]]
  402. %main = OpFunction %void None %8
  403. %17 = OpLabel
  404. %s0 = OpVariable %_ptr_Function_S_t Function
  405. %18 = OpLoad %v4float %BaseColor
  406. %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  407. OpStore %19 %18
  408. %20 = OpLoad %v4float %19
  409. OpStore %gl_FragColor %20
  410. OpReturn
  411. OpFunctionEnd
  412. )";
  413. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  414. true);
  415. }
  416. TEST_F(LocalAccessChainConvertTest, OpaqueConverted) {
  417. // SPIR-V not representable in GLSL; not generatable from HLSL
  418. // at the moment
  419. const std::string predefs =
  420. R"(
  421. OpCapability Shader
  422. %1 = OpExtInstImport "GLSL.std.450"
  423. OpMemoryModel Logical GLSL450
  424. OpEntryPoint Fragment %main "main" %outColor %texCoords
  425. OpExecutionMode %main OriginUpperLeft
  426. OpSource GLSL 140
  427. OpName %main "main"
  428. OpName %S_t "S_t"
  429. OpMemberName %S_t 0 "v0"
  430. OpMemberName %S_t 1 "v1"
  431. OpMemberName %S_t 2 "smp"
  432. OpName %foo_struct_S_t_vf2_vf21_ "foo(struct-S_t-vf2-vf21;"
  433. OpName %s "s"
  434. OpName %outColor "outColor"
  435. OpName %sampler15 "sampler15"
  436. OpName %s0 "s0"
  437. OpName %texCoords "texCoords"
  438. OpName %param "param"
  439. OpDecorate %sampler15 DescriptorSet 0
  440. %void = OpTypeVoid
  441. %12 = OpTypeFunction %void
  442. %float = OpTypeFloat 32
  443. %v2float = OpTypeVector %float 2
  444. %v4float = OpTypeVector %float 4
  445. %_ptr_Output_v4float = OpTypePointer Output %v4float
  446. %outColor = OpVariable %_ptr_Output_v4float Output
  447. %17 = OpTypeImage %float 2D 0 0 0 1 Unknown
  448. %18 = OpTypeSampledImage %17
  449. %S_t = OpTypeStruct %v2float %v2float %18
  450. %_ptr_Function_S_t = OpTypePointer Function %S_t
  451. %20 = OpTypeFunction %void %_ptr_Function_S_t
  452. %_ptr_UniformConstant_18 = OpTypePointer UniformConstant %18
  453. %_ptr_Function_18 = OpTypePointer Function %18
  454. %sampler15 = OpVariable %_ptr_UniformConstant_18 UniformConstant
  455. %int = OpTypeInt 32 1
  456. %int_0 = OpConstant %int 0
  457. %int_2 = OpConstant %int 2
  458. %_ptr_Function_v2float = OpTypePointer Function %v2float
  459. %_ptr_Input_v2float = OpTypePointer Input %v2float
  460. %texCoords = OpVariable %_ptr_Input_v2float Input
  461. )";
  462. const std::string before =
  463. R"(
  464. ; CHECK: [[l1:%\w+]] = OpLoad %S_t %param
  465. ; CHECK: [[e1:%\w+]] = OpCompositeExtract {{%\w+}} [[l1]] 2
  466. ; CHECK: [[l2:%\w+]] = OpLoad %S_t %param
  467. ; CHECK: [[e2:%\w+]] = OpCompositeExtract {{%\w+}} [[l2]] 0
  468. ; CHECK: OpImageSampleImplicitLod {{%\w+}} [[e1]] [[e2]]
  469. %main = OpFunction %void None %12
  470. %28 = OpLabel
  471. %s0 = OpVariable %_ptr_Function_S_t Function
  472. %param = OpVariable %_ptr_Function_S_t Function
  473. %29 = OpLoad %v2float %texCoords
  474. %30 = OpAccessChain %_ptr_Function_v2float %s0 %int_0
  475. OpStore %30 %29
  476. %31 = OpLoad %18 %sampler15
  477. %32 = OpAccessChain %_ptr_Function_18 %s0 %int_2
  478. OpStore %32 %31
  479. %33 = OpLoad %S_t %s0
  480. OpStore %param %33
  481. %34 = OpAccessChain %_ptr_Function_18 %param %int_2
  482. %35 = OpLoad %18 %34
  483. %36 = OpAccessChain %_ptr_Function_v2float %param %int_0
  484. %37 = OpLoad %v2float %36
  485. %38 = OpImageSampleImplicitLod %v4float %35 %37
  486. OpStore %outColor %38
  487. OpReturn
  488. OpFunctionEnd
  489. )";
  490. const std::string remain =
  491. R"(%foo_struct_S_t_vf2_vf21_ = OpFunction %void None %20
  492. %s = OpFunctionParameter %_ptr_Function_S_t
  493. %39 = OpLabel
  494. %40 = OpAccessChain %_ptr_Function_18 %s %int_2
  495. %41 = OpLoad %18 %40
  496. %42 = OpAccessChain %_ptr_Function_v2float %s %int_0
  497. %43 = OpLoad %v2float %42
  498. %44 = OpImageSampleImplicitLod %v4float %41 %43
  499. OpStore %outColor %44
  500. OpReturn
  501. OpFunctionEnd
  502. )";
  503. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before + remain,
  504. true);
  505. }
  506. TEST_F(LocalAccessChainConvertTest, NestedStructsConverted) {
  507. // #version 140
  508. //
  509. // in vec4 BaseColor;
  510. //
  511. // struct S1_t {
  512. // vec4 v1;
  513. // };
  514. //
  515. // struct S2_t {
  516. // vec4 v2;
  517. // S1_t s1;
  518. // };
  519. //
  520. // void main()
  521. // {
  522. // S2_t s2;
  523. // s2.s1.v1 = BaseColor;
  524. // gl_FragColor = s2.s1.v1;
  525. // }
  526. const std::string predefs_before =
  527. R"(OpCapability Shader
  528. %1 = OpExtInstImport "GLSL.std.450"
  529. OpMemoryModel Logical GLSL450
  530. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  531. OpExecutionMode %main OriginUpperLeft
  532. OpSource GLSL 140
  533. OpName %main "main"
  534. OpName %S1_t "S1_t"
  535. OpMemberName %S1_t 0 "v1"
  536. OpName %S2_t "S2_t"
  537. OpMemberName %S2_t 0 "v2"
  538. OpMemberName %S2_t 1 "s1"
  539. OpName %s2 "s2"
  540. OpName %BaseColor "BaseColor"
  541. OpName %gl_FragColor "gl_FragColor"
  542. %void = OpTypeVoid
  543. %9 = OpTypeFunction %void
  544. %float = OpTypeFloat 32
  545. %v4float = OpTypeVector %float 4
  546. %S1_t = OpTypeStruct %v4float
  547. %S2_t = OpTypeStruct %v4float %S1_t
  548. %_ptr_Function_S2_t = OpTypePointer Function %S2_t
  549. %int = OpTypeInt 32 1
  550. %int_1 = OpConstant %int 1
  551. %int_0 = OpConstant %int 0
  552. %_ptr_Input_v4float = OpTypePointer Input %v4float
  553. %BaseColor = OpVariable %_ptr_Input_v4float Input
  554. %_ptr_Function_v4float = OpTypePointer Function %v4float
  555. %_ptr_Output_v4float = OpTypePointer Output %v4float
  556. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  557. )";
  558. const std::string before =
  559. R"(
  560. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  561. ; CHECK: [[ld1:%\w+]] = OpLoad %S2_t %s2
  562. ; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S2_t [[st_id]] [[ld1]] 1 0
  563. ; CHECK: OpStore %s2 [[ex1]]
  564. ; CHECK: [[ld2:%\w+]] = OpLoad %S2_t %s2
  565. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 0
  566. ; CHECK: OpStore %gl_FragColor [[ex2]]
  567. %main = OpFunction %void None %9
  568. %19 = OpLabel
  569. %s2 = OpVariable %_ptr_Function_S2_t Function
  570. %20 = OpLoad %v4float %BaseColor
  571. %21 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0
  572. OpStore %21 %20
  573. %22 = OpAccessChain %_ptr_Function_v4float %s2 %int_1 %int_0
  574. %23 = OpLoad %v4float %22
  575. OpStore %gl_FragColor %23
  576. OpReturn
  577. OpFunctionEnd
  578. )";
  579. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  580. true);
  581. }
  582. TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) {
  583. // Based on HLSL source code:
  584. // struct S {
  585. // float f;
  586. // };
  587. // float main(float input : A) : B {
  588. // S local = { input };
  589. // return local.f;
  590. // }
  591. const std::string predefs = R"(OpCapability Shader
  592. OpMemoryModel Logical GLSL450
  593. OpEntryPoint Vertex %main "main" %in_var_A %out_var_B
  594. OpName %main "main"
  595. OpName %in_var_A "in.var.A"
  596. OpName %out_var_B "out.var.B"
  597. OpName %S "S"
  598. OpName %local "local"
  599. %int = OpTypeInt 32 1
  600. %void = OpTypeVoid
  601. %8 = OpTypeFunction %void
  602. %float = OpTypeFloat 32
  603. %_ptr_Function_float = OpTypePointer Function %float
  604. %_ptr_Input_float = OpTypePointer Input %float
  605. %_ptr_Output_float = OpTypePointer Output %float
  606. %S = OpTypeStruct %float
  607. %_ptr_Function_S = OpTypePointer Function %S
  608. %int_0 = OpConstant %int 0
  609. %in_var_A = OpVariable %_ptr_Input_float Input
  610. %out_var_B = OpVariable %_ptr_Output_float Output
  611. %main = OpFunction %void None %8
  612. %15 = OpLabel
  613. %local = OpVariable %_ptr_Function_S Function
  614. %16 = OpLoad %float %in_var_A
  615. %17 = OpCompositeConstruct %S %16
  616. OpStore %local %17
  617. )";
  618. const std::string before =
  619. R"(
  620. ; CHECK: [[ld:%\w+]] = OpLoad %S %local
  621. ; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0
  622. ; CHECK: OpStore %out_var_B [[ex]]
  623. %18 = OpAccessChain %_ptr_Function_float %local %int_0
  624. %19 = OpAccessChain %_ptr_Function_float %local %int_0
  625. %20 = OpLoad %float %18
  626. OpStore %out_var_B %20
  627. OpReturn
  628. OpFunctionEnd
  629. )";
  630. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before, true);
  631. }
  632. TEST_F(LocalAccessChainConvertTest,
  633. StructOfVecsOfFloatConvertedWithDecorationOnLoad) {
  634. // #version 140
  635. //
  636. // in vec4 BaseColor;
  637. //
  638. // struct S_t {
  639. // vec4 v0;
  640. // vec4 v1;
  641. // };
  642. //
  643. // void main()
  644. // {
  645. // S_t s0;
  646. // s0.v1 = BaseColor;
  647. // gl_FragColor = s0.v1;
  648. // }
  649. const std::string predefs_before =
  650. R"(OpCapability Shader
  651. %1 = OpExtInstImport "GLSL.std.450"
  652. OpMemoryModel Logical GLSL450
  653. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  654. OpExecutionMode %main OriginUpperLeft
  655. OpSource GLSL 140
  656. OpName %main "main"
  657. OpName %S_t "S_t"
  658. OpMemberName %S_t 0 "v0"
  659. OpMemberName %S_t 1 "v1"
  660. OpName %s0 "s0"
  661. OpName %BaseColor "BaseColor"
  662. OpName %gl_FragColor "gl_FragColor"
  663. OpDecorate %21 RelaxedPrecision
  664. %void = OpTypeVoid
  665. %8 = OpTypeFunction %void
  666. %float = OpTypeFloat 32
  667. %v4float = OpTypeVector %float 4
  668. %S_t = OpTypeStruct %v4float %v4float
  669. %_ptr_Function_S_t = OpTypePointer Function %S_t
  670. %int = OpTypeInt 32 1
  671. %int_1 = OpConstant %int 1
  672. %_ptr_Input_v4float = OpTypePointer Input %v4float
  673. %BaseColor = OpVariable %_ptr_Input_v4float Input
  674. %_ptr_Function_v4float = OpTypePointer Function %v4float
  675. %_ptr_Output_v4float = OpTypePointer Output %v4float
  676. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  677. )";
  678. const std::string before =
  679. R"(
  680. ; CHECK: OpDecorate
  681. ; CHECK: OpDecorate [[ld2:%\w+]] RelaxedPrecision
  682. ; CHECK-NOT: OpDecorate
  683. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  684. ; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
  685. ; CHECK: [[ins:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
  686. ; CHECK: OpStore %s0 [[ins]]
  687. ; CHECK: [[ld2]] = OpLoad %S_t %s0
  688. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
  689. ; CHECK: OpStore %gl_FragColor [[ex2]]
  690. %main = OpFunction %void None %8
  691. %17 = OpLabel
  692. %s0 = OpVariable %_ptr_Function_S_t Function
  693. %18 = OpLoad %v4float %BaseColor
  694. %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  695. OpStore %19 %18
  696. %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  697. %21 = OpLoad %v4float %20
  698. OpStore %gl_FragColor %21
  699. OpReturn
  700. OpFunctionEnd
  701. )";
  702. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  703. true);
  704. }
  705. TEST_F(LocalAccessChainConvertTest,
  706. StructOfVecsOfFloatConvertedWithDecorationOnStore) {
  707. // #version 140
  708. //
  709. // in vec4 BaseColor;
  710. //
  711. // struct S_t {
  712. // vec4 v0;
  713. // vec4 v1;
  714. // };
  715. //
  716. // void main()
  717. // {
  718. // S_t s0;
  719. // s0.v1 = BaseColor;
  720. // gl_FragColor = s0.v1;
  721. // }
  722. const std::string predefs_before =
  723. R"(OpCapability Shader
  724. %1 = OpExtInstImport "GLSL.std.450"
  725. OpMemoryModel Logical GLSL450
  726. OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
  727. OpExecutionMode %main OriginUpperLeft
  728. OpSource GLSL 140
  729. OpName %main "main"
  730. OpName %S_t "S_t"
  731. OpMemberName %S_t 0 "v0"
  732. OpMemberName %S_t 1 "v1"
  733. OpName %s0 "s0"
  734. OpName %BaseColor "BaseColor"
  735. OpName %gl_FragColor "gl_FragColor"
  736. OpDecorate %s0 RelaxedPrecision
  737. %void = OpTypeVoid
  738. %8 = OpTypeFunction %void
  739. %float = OpTypeFloat 32
  740. %v4float = OpTypeVector %float 4
  741. %S_t = OpTypeStruct %v4float %v4float
  742. %_ptr_Function_S_t = OpTypePointer Function %S_t
  743. %int = OpTypeInt 32 1
  744. %int_1 = OpConstant %int 1
  745. %_ptr_Input_v4float = OpTypePointer Input %v4float
  746. %BaseColor = OpVariable %_ptr_Input_v4float Input
  747. %_ptr_Function_v4float = OpTypePointer Function %v4float
  748. %_ptr_Output_v4float = OpTypePointer Output %v4float
  749. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  750. )";
  751. const std::string before =
  752. R"(
  753. ; CHECK: OpDecorate
  754. ; CHECK: OpDecorate [[ld1:%\w+]] RelaxedPrecision
  755. ; CHECK: OpDecorate [[ins:%\w+]] RelaxedPrecision
  756. ; CHECK-NOT: OpDecorate
  757. ; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
  758. ; CHECK: [[ld1]] = OpLoad %S_t %s0
  759. ; CHECK: [[ins]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
  760. ; CHECK: OpStore %s0 [[ins]]
  761. ; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
  762. ; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
  763. ; CHECK: OpStore %gl_FragColor [[ex2]]
  764. %main = OpFunction %void None %8
  765. %17 = OpLabel
  766. %s0 = OpVariable %_ptr_Function_S_t Function
  767. %18 = OpLoad %v4float %BaseColor
  768. %19 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  769. OpStore %19 %18
  770. %20 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  771. %21 = OpLoad %v4float %20
  772. OpStore %gl_FragColor %21
  773. OpReturn
  774. OpFunctionEnd
  775. )";
  776. SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
  777. true);
  778. }
  779. TEST_F(LocalAccessChainConvertTest, DynamicallyIndexedVarNotConverted) {
  780. // #version 140
  781. //
  782. // in vec4 BaseColor;
  783. // flat in int Idx;
  784. // in float Bi;
  785. //
  786. // struct S_t {
  787. // vec4 v0;
  788. // vec4 v1;
  789. // };
  790. //
  791. // void main()
  792. // {
  793. // S_t s0;
  794. // s0.v1 = BaseColor;
  795. // s0.v1[Idx] = Bi;
  796. // gl_FragColor = s0.v1;
  797. // }
  798. const std::string assembly =
  799. R"(OpCapability Shader
  800. %1 = OpExtInstImport "GLSL.std.450"
  801. OpMemoryModel Logical GLSL450
  802. OpEntryPoint Fragment %main "main" %BaseColor %Idx %Bi %gl_FragColor
  803. OpExecutionMode %main OriginUpperLeft
  804. OpSource GLSL 140
  805. OpName %main "main"
  806. OpName %S_t "S_t"
  807. OpMemberName %S_t 0 "v0"
  808. OpMemberName %S_t 1 "v1"
  809. OpName %s0 "s0"
  810. OpName %BaseColor "BaseColor"
  811. OpName %Idx "Idx"
  812. OpName %Bi "Bi"
  813. OpName %gl_FragColor "gl_FragColor"
  814. OpDecorate %Idx Flat
  815. %void = OpTypeVoid
  816. %10 = OpTypeFunction %void
  817. %float = OpTypeFloat 32
  818. %v4float = OpTypeVector %float 4
  819. %S_t = OpTypeStruct %v4float %v4float
  820. %_ptr_Function_S_t = OpTypePointer Function %S_t
  821. %int = OpTypeInt 32 1
  822. %int_1 = OpConstant %int 1
  823. %_ptr_Input_v4float = OpTypePointer Input %v4float
  824. %BaseColor = OpVariable %_ptr_Input_v4float Input
  825. %_ptr_Function_v4float = OpTypePointer Function %v4float
  826. %_ptr_Input_int = OpTypePointer Input %int
  827. %Idx = OpVariable %_ptr_Input_int Input
  828. %_ptr_Input_float = OpTypePointer Input %float
  829. %Bi = OpVariable %_ptr_Input_float Input
  830. %_ptr_Function_float = OpTypePointer Function %float
  831. %_ptr_Output_v4float = OpTypePointer Output %v4float
  832. %gl_FragColor = OpVariable %_ptr_Output_v4float Output
  833. %main = OpFunction %void None %10
  834. %22 = OpLabel
  835. %s0 = OpVariable %_ptr_Function_S_t Function
  836. %23 = OpLoad %v4float %BaseColor
  837. %24 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  838. OpStore %24 %23
  839. %25 = OpLoad %int %Idx
  840. %26 = OpLoad %float %Bi
  841. %27 = OpAccessChain %_ptr_Function_float %s0 %int_1 %25
  842. OpStore %27 %26
  843. %28 = OpAccessChain %_ptr_Function_v4float %s0 %int_1
  844. %29 = OpLoad %v4float %28
  845. OpStore %gl_FragColor %29
  846. OpReturn
  847. OpFunctionEnd
  848. )";
  849. SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
  850. true);
  851. }
  852. TEST_F(LocalAccessChainConvertTest, VariablePointersStorageBuffer) {
  853. // A case with a storage buffer variable pointer. We should still convert
  854. // the access chain on the function scope symbol.
  855. const std::string test =
  856. R"(
  857. ; CHECK: OpFunction
  858. ; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Function
  859. ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[var]]
  860. ; CHECK: OpCompositeExtract {{%\w+}} [[ld]] 0 0
  861. OpCapability Shader
  862. OpCapability VariablePointersStorageBuffer
  863. %1 = OpExtInstImport "GLSL.std.450"
  864. OpMemoryModel Logical GLSL450
  865. OpEntryPoint GLCompute %2 "main"
  866. OpExecutionMode %2 LocalSize 1 1 1
  867. OpSource GLSL 450
  868. OpMemberDecorate %_struct_3 0 Offset 0
  869. OpDecorate %_struct_3 Block
  870. OpDecorate %4 DescriptorSet 0
  871. OpDecorate %4 Binding 0
  872. OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
  873. OpDecorate %_arr_int_int_128 ArrayStride 4
  874. %void = OpTypeVoid
  875. %8 = OpTypeFunction %void
  876. %int = OpTypeInt 32 1
  877. %int_128 = OpConstant %int 128
  878. %_arr_int_int_128 = OpTypeArray %int %int_128
  879. %_struct_3 = OpTypeStruct %_arr_int_int_128
  880. %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
  881. %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
  882. %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
  883. %bool = OpTypeBool
  884. %true = OpConstantTrue %bool
  885. %int_0 = OpConstant %int 0
  886. %int_1 = OpConstant %int 1
  887. %_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
  888. %_ptr_Function_int = OpTypePointer Function %int
  889. %2 = OpFunction %void None %8
  890. %18 = OpLabel
  891. %19 = OpVariable %_ptr_Function__struct_3 Function
  892. %20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
  893. OpBranch %21
  894. %21 = OpLabel
  895. %22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24
  896. OpLoopMerge %25 %24 None
  897. OpBranchConditional %true %26 %25
  898. %26 = OpLabel
  899. OpStore %22 %int_0
  900. OpBranch %24
  901. %24 = OpLabel
  902. %23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1
  903. OpBranch %21
  904. %25 = OpLabel
  905. %27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0
  906. %28 = OpLoad %int %27
  907. OpReturn
  908. OpFunctionEnd
  909. )";
  910. SinglePassRunAndMatch<LocalAccessChainConvertPass>(test, true);
  911. }
  912. TEST_F(LocalAccessChainConvertTest, VariablePointers) {
  913. // A case with variable pointer capability. We should not convert
  914. // the access chain on the function scope symbol because the variable pointer
  915. // could the analysis to miss references to function scope symbols.
  916. const std::string test =
  917. R"(OpCapability Shader
  918. OpCapability VariablePointers
  919. %1 = OpExtInstImport "GLSL.std.450"
  920. OpMemoryModel Logical GLSL450
  921. OpEntryPoint GLCompute %2 "main"
  922. OpExecutionMode %2 LocalSize 1 1 1
  923. OpSource GLSL 450
  924. OpMemberDecorate %_struct_3 0 Offset 0
  925. OpDecorate %_struct_3 Block
  926. OpDecorate %4 DescriptorSet 0
  927. OpDecorate %4 Binding 0
  928. OpDecorate %_ptr_StorageBuffer_int ArrayStride 4
  929. OpDecorate %_arr_int_int_128 ArrayStride 4
  930. %void = OpTypeVoid
  931. %8 = OpTypeFunction %void
  932. %int = OpTypeInt 32 1
  933. %int_128 = OpConstant %int 128
  934. %_arr_int_int_128 = OpTypeArray %int %int_128
  935. %_struct_3 = OpTypeStruct %_arr_int_int_128
  936. %_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
  937. %_ptr_Function__struct_3 = OpTypePointer Function %_struct_3
  938. %4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer
  939. %bool = OpTypeBool
  940. %true = OpConstantTrue %bool
  941. %int_0 = OpConstant %int 0
  942. %int_1 = OpConstant %int 1
  943. %_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int
  944. %_ptr_Function_int = OpTypePointer Function %int
  945. %2 = OpFunction %void None %8
  946. %18 = OpLabel
  947. %19 = OpVariable %_ptr_Function__struct_3 Function
  948. %20 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0
  949. OpBranch %21
  950. %21 = OpLabel
  951. %22 = OpPhi %_ptr_StorageBuffer_int %20 %18 %23 %24
  952. OpLoopMerge %25 %24 None
  953. OpBranchConditional %true %26 %25
  954. %26 = OpLabel
  955. OpStore %22 %int_0
  956. OpBranch %24
  957. %24 = OpLabel
  958. %23 = OpPtrAccessChain %_ptr_StorageBuffer_int %22 %int_1
  959. OpBranch %21
  960. %25 = OpLabel
  961. %27 = OpAccessChain %_ptr_Function_int %19 %int_0 %int_0
  962. %28 = OpLoad %int %27
  963. OpReturn
  964. OpFunctionEnd
  965. )";
  966. SinglePassRunAndCheck<LocalAccessChainConvertPass>(test, test, false, true);
  967. }
  968. TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingLoad) {
  969. const std::string text =
  970. R"(
  971. OpCapability Shader
  972. OpMemoryModel Logical GLSL450
  973. OpEntryPoint Fragment %4 "PSMain"
  974. OpExecutionMode %4 OriginUpperLeft
  975. OpDecorate %10 Location 47360
  976. %void = OpTypeVoid
  977. %3 = OpTypeFunction %void
  978. %float = OpTypeFloat 32
  979. %v4float = OpTypeVector %float 4
  980. %_struct_8 = OpTypeStruct %v4float
  981. %_ptr_Function__struct_8 = OpTypePointer Function %_struct_8
  982. %int = OpTypeInt 32 1
  983. %int_0 = OpConstant %int 0
  984. %_ptr_Function_v4float = OpTypePointer Function %v4float
  985. %4 = OpFunction %void None %3
  986. %5 = OpLabel
  987. %10 = OpVariable %_ptr_Function__struct_8 Function
  988. %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0
  989. %4194302 = OpLoad %v4float %4194301
  990. OpReturn
  991. OpFunctionEnd
  992. )";
  993. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  994. std::vector<Message> messages = {
  995. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
  996. SetMessageConsumer(GetTestMessageConsumer(messages));
  997. auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
  998. EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
  999. }
  1000. TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore1) {
  1001. const std::string text =
  1002. R"(
  1003. OpCapability Shader
  1004. OpMemoryModel Logical GLSL450
  1005. OpEntryPoint Fragment %4 "PSMain"
  1006. OpExecutionMode %4 OriginUpperLeft
  1007. OpDecorate %10 Location 47360
  1008. %void = OpTypeVoid
  1009. %3 = OpTypeFunction %void
  1010. %float = OpTypeFloat 32
  1011. %v4float = OpTypeVector %float 4
  1012. %_struct_7 = OpTypeStruct %v4float
  1013. %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
  1014. %int = OpTypeInt 32 1
  1015. %int_0 = OpConstant %int 0
  1016. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1017. %13 = OpConstantNull %v4float
  1018. %4 = OpFunction %void None %3
  1019. %5 = OpLabel
  1020. %10 = OpVariable %_ptr_Function__struct_7 Function
  1021. %4194302 = OpAccessChain %_ptr_Function_v4float %10 %int_0
  1022. OpStore %4194302 %13
  1023. OpReturn
  1024. OpFunctionEnd
  1025. )";
  1026. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1027. std::vector<Message> messages = {
  1028. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
  1029. SetMessageConsumer(GetTestMessageConsumer(messages));
  1030. auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
  1031. EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
  1032. }
  1033. TEST_F(LocalAccessChainConvertTest, IdOverflowReplacingStore2) {
  1034. const std::string text =
  1035. R"(
  1036. OpCapability Shader
  1037. OpMemoryModel Logical GLSL450
  1038. OpEntryPoint Fragment %4 "PSMain"
  1039. OpExecutionMode %4 OriginUpperLeft
  1040. OpDecorate %10 Location 47360
  1041. %void = OpTypeVoid
  1042. %3 = OpTypeFunction %void
  1043. %float = OpTypeFloat 32
  1044. %v4float = OpTypeVector %float 4
  1045. %_struct_7 = OpTypeStruct %v4float
  1046. %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
  1047. %int = OpTypeInt 32 1
  1048. %int_0 = OpConstant %int 0
  1049. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1050. %13 = OpConstantNull %v4float
  1051. %4 = OpFunction %void None %3
  1052. %5 = OpLabel
  1053. %10 = OpVariable %_ptr_Function__struct_7 Function
  1054. %4194301 = OpAccessChain %_ptr_Function_v4float %10 %int_0
  1055. OpStore %4194301 %13
  1056. OpReturn
  1057. OpFunctionEnd
  1058. )";
  1059. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  1060. std::vector<Message> messages = {
  1061. {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
  1062. SetMessageConsumer(GetTestMessageConsumer(messages));
  1063. auto result = SinglePassRunToBinary<LocalAccessChainConvertPass>(text, true);
  1064. EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
  1065. }
  1066. TEST_F(LocalAccessChainConvertTest, AccessChainWithNoIndex) {
  1067. const std::string before =
  1068. R"(
  1069. ; CHECK: OpFunction
  1070. ; CHECK: [[var:%\w+]] = OpVariable
  1071. ; CHECK: OpStore [[var]] %true
  1072. ; CHECK: OpLoad %bool [[var]]
  1073. OpCapability Shader
  1074. %1 = OpExtInstImport "GLSL.std.450"
  1075. OpMemoryModel Logical GLSL450
  1076. OpEntryPoint Fragment %2 "main"
  1077. OpExecutionMode %2 OriginUpperLeft
  1078. OpSource ESSL 310
  1079. %void = OpTypeVoid
  1080. %4 = OpTypeFunction %void
  1081. %bool = OpTypeBool
  1082. %true = OpConstantTrue %bool
  1083. %_ptr_Function_bool = OpTypePointer Function %bool
  1084. %2 = OpFunction %void None %4
  1085. %8 = OpLabel
  1086. %9 = OpVariable %_ptr_Function_bool Function
  1087. %10 = OpAccessChain %_ptr_Function_bool %9
  1088. OpStore %10 %true
  1089. %11 = OpLoad %bool %10
  1090. OpReturn
  1091. OpFunctionEnd
  1092. )";
  1093. SinglePassRunAndMatch<LocalAccessChainConvertPass>(before, true);
  1094. }
  1095. TEST_F(LocalAccessChainConvertTest, AccessChainWithLongIndex) {
  1096. // The access chain take a value that is larger than 32-bit. The index cannot
  1097. // be encoded in an OpCompositeExtract, so nothing should be done.
  1098. const std::string before =
  1099. R"(OpCapability Shader
  1100. OpCapability Int64
  1101. %1 = OpExtInstImport "GLSL.std.450"
  1102. OpMemoryModel Logical GLSL450
  1103. OpEntryPoint Fragment %2 "main_0004f4d4_85b2f584"
  1104. OpExecutionMode %2 OriginUpperLeft
  1105. %ulong = OpTypeInt 64 0
  1106. %ulong_8589934592 = OpConstant %ulong 8589934592
  1107. %ulong_8589934591 = OpConstant %ulong 8589934591
  1108. %_arr_ulong_ulong_8589934592 = OpTypeArray %ulong %ulong_8589934592
  1109. %_ptr_Function__arr_ulong_ulong_8589934592 = OpTypePointer Function %_arr_ulong_ulong_8589934592
  1110. %_ptr_Function_ulong = OpTypePointer Function %ulong
  1111. %void = OpTypeVoid
  1112. %10 = OpTypeFunction %void
  1113. %2 = OpFunction %void None %10
  1114. %11 = OpLabel
  1115. %12 = OpVariable %_ptr_Function__arr_ulong_ulong_8589934592 Function
  1116. %13 = OpAccessChain %_ptr_Function_ulong %12 %ulong_8589934591
  1117. %14 = OpLoad %ulong %13
  1118. OpReturn
  1119. OpFunctionEnd
  1120. )";
  1121. SinglePassRunAndCheck<LocalAccessChainConvertPass>(before, before, false,
  1122. true);
  1123. }
  1124. TEST_F(LocalAccessChainConvertTest, AccessChainWith32BitIndexInLong) {
  1125. // The access chain has a value that is 32-bits, but it is stored in a 64-bit
  1126. // variable. This access change can be converted to an extract.
  1127. const std::string before =
  1128. R"(
  1129. ; CHECK: OpFunction
  1130. ; CHECK: [[var:%\w+]] = OpVariable
  1131. ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[var]]
  1132. ; CHECK: OpCompositeExtract %ulong [[ld]] 3
  1133. OpCapability Shader
  1134. OpCapability Int64
  1135. %1 = OpExtInstImport "GLSL.std.450"
  1136. OpMemoryModel Logical GLSL450
  1137. OpEntryPoint Fragment %2 "main_0004f4d4_85b2f584"
  1138. OpExecutionMode %2 OriginUpperLeft
  1139. %ulong = OpTypeInt 64 0
  1140. %ulong_8589934592 = OpConstant %ulong 8589934592
  1141. %ulong_3 = OpConstant %ulong 3
  1142. %_arr_ulong_ulong_8589934592 = OpTypeArray %ulong %ulong_8589934592
  1143. %_ptr_Function__arr_ulong_ulong_8589934592 = OpTypePointer Function %_arr_ulong_ulong_8589934592
  1144. %_ptr_Function_ulong = OpTypePointer Function %ulong
  1145. %void = OpTypeVoid
  1146. %10 = OpTypeFunction %void
  1147. %2 = OpFunction %void None %10
  1148. %11 = OpLabel
  1149. %12 = OpVariable %_ptr_Function__arr_ulong_ulong_8589934592 Function
  1150. %13 = OpAccessChain %_ptr_Function_ulong %12 %ulong_3
  1151. %14 = OpLoad %ulong %13
  1152. OpReturn
  1153. OpFunctionEnd
  1154. )";
  1155. SinglePassRunAndMatch<LocalAccessChainConvertPass>(before, true);
  1156. }
  1157. TEST_F(LocalAccessChainConvertTest, AccessChainWithVarIndex) {
  1158. // The access chain has a value that is not constant, so there should not be
  1159. // any changes.
  1160. const std::string before =
  1161. R"(OpCapability Shader
  1162. %1 = OpExtInstImport "GLSL.std.450"
  1163. OpMemoryModel Logical GLSL450
  1164. OpEntryPoint Fragment %2 "main_0004f4d4_85b2f584"
  1165. OpExecutionMode %2 OriginUpperLeft
  1166. %uint = OpTypeInt 32 0
  1167. %uint_5 = OpConstant %uint 5
  1168. %_arr_uint_uint_5 = OpTypeArray %uint %uint_5
  1169. %_ptr_Function__arr_uint_uint_5 = OpTypePointer Function %_arr_uint_uint_5
  1170. %_ptr_Function_uint = OpTypePointer Function %uint
  1171. %8 = OpUndef %uint
  1172. %void = OpTypeVoid
  1173. %10 = OpTypeFunction %void
  1174. %2 = OpFunction %void None %10
  1175. %11 = OpLabel
  1176. %12 = OpVariable %_ptr_Function__arr_uint_uint_5 Function
  1177. %13 = OpAccessChain %_ptr_Function_uint %12 %8
  1178. %14 = OpLoad %uint %13
  1179. OpReturn
  1180. OpFunctionEnd
  1181. )";
  1182. SinglePassRunAndCheck<LocalAccessChainConvertPass>(before, before, false,
  1183. true);
  1184. }
  1185. TEST_F(LocalAccessChainConvertTest, OutOfBoundsAccess) {
  1186. // The access chain indexes element 12 in an array of size 10. Nothing should
  1187. // be done.
  1188. const std::string assembly =
  1189. R"(OpCapability Shader
  1190. %1 = OpExtInstImport "GLSL.std.450"
  1191. OpMemoryModel Logical GLSL450
  1192. OpEntryPoint Fragment %2 "main" %3
  1193. OpExecutionMode %2 OriginUpperLeft
  1194. %void = OpTypeVoid
  1195. %5 = OpTypeFunction %void
  1196. %int = OpTypeInt 32 1
  1197. %int_10 = OpConstant %int 10
  1198. %_arr_int_int_10 = OpTypeArray %int %int_10
  1199. %_ptr_Function_int = OpTypePointer Function %int
  1200. %int_12 = OpConstant %int 12
  1201. %_ptr_Output_int = OpTypePointer Output %int
  1202. %3 = OpVariable %_ptr_Output_int Output
  1203. %_ptr_Function__arr_int_int_10 = OpTypePointer Function %_arr_int_int_10
  1204. %2 = OpFunction %void None %5
  1205. %13 = OpLabel
  1206. %14 = OpVariable %_ptr_Function__arr_int_int_10 Function
  1207. %15 = OpAccessChain %_ptr_Function_int %14 %int_12
  1208. %16 = OpLoad %int %15
  1209. OpStore %3 %16
  1210. OpReturn
  1211. OpFunctionEnd
  1212. )";
  1213. SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
  1214. true);
  1215. }
  1216. TEST_F(LocalAccessChainConvertTest, OutOfBoundsAccessAtBoundary) {
  1217. // The access chain indexes element 10 in an array of size 10. Nothing should
  1218. // be done.
  1219. const std::string assembly =
  1220. R"(OpCapability Shader
  1221. %1 = OpExtInstImport "GLSL.std.450"
  1222. OpMemoryModel Logical GLSL450
  1223. OpEntryPoint Fragment %2 "main" %3
  1224. OpExecutionMode %2 OriginUpperLeft
  1225. %void = OpTypeVoid
  1226. %5 = OpTypeFunction %void
  1227. %int = OpTypeInt 32 1
  1228. %int_10 = OpConstant %int 10
  1229. %_arr_int_int_10 = OpTypeArray %int %int_10
  1230. %_ptr_Function_int = OpTypePointer Function %int
  1231. %_ptr_Output_int = OpTypePointer Output %int
  1232. %3 = OpVariable %_ptr_Output_int Output
  1233. %_ptr_Function__arr_int_int_10 = OpTypePointer Function %_arr_int_int_10
  1234. %2 = OpFunction %void None %5
  1235. %12 = OpLabel
  1236. %13 = OpVariable %_ptr_Function__arr_int_int_10 Function
  1237. %14 = OpAccessChain %_ptr_Function_int %13 %int_10
  1238. %15 = OpLoad %int %14
  1239. OpStore %3 %15
  1240. OpReturn
  1241. OpFunctionEnd
  1242. )";
  1243. SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
  1244. true);
  1245. }
  1246. TEST_F(LocalAccessChainConvertTest, NegativeIndex) {
  1247. // The access chain has a negative index and should not be converted because
  1248. // the extract instruction cannot hold a negative number.
  1249. const std::string assembly =
  1250. R"(OpCapability Shader
  1251. %1 = OpExtInstImport "GLSL.std.450"
  1252. OpMemoryModel Logical GLSL450
  1253. OpEntryPoint Fragment %2 "main"
  1254. OpExecutionMode %2 OriginUpperLeft
  1255. %void = OpTypeVoid
  1256. %4 = OpTypeFunction %void
  1257. %int = OpTypeInt 32 1
  1258. %uint = OpTypeInt 32 0
  1259. %uint_3808428041 = OpConstant %uint 3808428041
  1260. %_arr_int_uint_3808428041 = OpTypeArray %int %uint_3808428041
  1261. %_ptr_Function__arr_int_uint_3808428041 = OpTypePointer Function %_arr_int_uint_3808428041
  1262. %_ptr_Function_int = OpTypePointer Function %int
  1263. %int_n1272971256 = OpConstant %int -1272971256
  1264. %2 = OpFunction %void None %4
  1265. %12 = OpLabel
  1266. %13 = OpVariable %_ptr_Function__arr_int_uint_3808428041 Function
  1267. %14 = OpAccessChain %_ptr_Function_int %13 %int_n1272971256
  1268. %15 = OpLoad %int %14
  1269. OpReturn
  1270. OpFunctionEnd
  1271. )";
  1272. SinglePassRunAndCheck<LocalAccessChainConvertPass>(assembly, assembly, false,
  1273. true);
  1274. }
  1275. TEST_F(LocalAccessChainConvertTest, VkMemoryModelTest) {
  1276. const std::string text =
  1277. R"(
  1278. ; CHECK: OpCapability Shader
  1279. ; CHECK: OpCapability VulkanMemoryModel
  1280. ; CHECK: OpExtension "SPV_KHR_vulkan_memory_model"
  1281. OpCapability Shader
  1282. OpCapability VulkanMemoryModel
  1283. OpExtension "SPV_KHR_vulkan_memory_model"
  1284. %1 = OpExtInstImport "GLSL.std.450"
  1285. OpMemoryModel Logical Vulkan
  1286. OpEntryPoint GLCompute %main "main"
  1287. OpExecutionMode %main LocalSize 1 1 1
  1288. OpSource GLSL 450
  1289. OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
  1290. OpSourceExtension "GL_GOOGLE_include_directive"
  1291. OpName %main "main"
  1292. OpName %a "a"
  1293. %void = OpTypeVoid
  1294. %3 = OpTypeFunction %void
  1295. %float = OpTypeFloat 32
  1296. %v4float = OpTypeVector %float 4
  1297. %_ptr_Function_v4float = OpTypePointer Function %v4float
  1298. %uint = OpTypeInt 32 0
  1299. %uint_0 = OpConstant %uint 0
  1300. %_ptr_Function_float = OpTypePointer Function %float
  1301. %float_1 = OpConstant %float 1
  1302. ; CHECK: OpFunction
  1303. ; CHECK-NEXT: OpLabel
  1304. ; CHECK-NEXT: [[a:%\w+]] = OpVariable
  1305. ; Make sure the access chains were removed.
  1306. ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[a]]
  1307. ; CHECK: [[ex:%\w+]] = OpCompositeExtract {{%\w+}} [[ld]] 0
  1308. ; CHECK: [[ld2:%\w+]] = OpLoad {{%\w+}} [[a]]
  1309. ; CHECK: [[v:%\w+]] = OpCompositeInsert {{%\w+}} [[ex]] [[ld2]] 0
  1310. ; CHECK: OpStore [[a]] [[v]]
  1311. %main = OpFunction %void None %3
  1312. %5 = OpLabel
  1313. %a = OpVariable %_ptr_Function_v4float Function
  1314. %13 = OpAccessChain %_ptr_Function_float %a %uint_0
  1315. %14 = OpLoad %float %13
  1316. %17 = OpAccessChain %_ptr_Function_float %a %uint_0
  1317. OpStore %17 %14
  1318. OpReturn
  1319. OpFunctionEnd
  1320. )";
  1321. SinglePassRunAndMatch<LocalAccessChainConvertPass>(text, false);
  1322. }
  1323. // TODO(greg-lunarg): Add tests to verify handling of these cases:
  1324. //
  1325. // Assorted vector and matrix types
  1326. // Assorted struct array types
  1327. // Assorted scalar types
  1328. // Assorted non-target types
  1329. // OpInBoundsAccessChain
  1330. // Others?
  1331. } // namespace
  1332. } // namespace opt
  1333. } // namespace spvtools