collect_shader_info_pass.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "shader_recompiler/environment.h"
  5. #include "shader_recompiler/frontend/ir/microinstruction.h"
  6. #include "shader_recompiler/frontend/ir/modifiers.h"
  7. #include "shader_recompiler/frontend/ir/program.h"
  8. #include "shader_recompiler/shader_info.h"
  9. namespace Shader::Optimization {
  10. namespace {
  11. void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) {
  12. if (count != 1) {
  13. throw NotImplementedException("Constant buffer descriptor indexing");
  14. }
  15. if ((info.constant_buffer_mask & (1U << index)) != 0) {
  16. return;
  17. }
  18. info.constant_buffer_mask |= 1U << index;
  19. auto& cbufs{info.constant_buffer_descriptors};
  20. cbufs.insert(std::ranges::lower_bound(cbufs, index, {}, &ConstantBufferDescriptor::index),
  21. ConstantBufferDescriptor{
  22. .index{index},
  23. .count{1},
  24. });
  25. }
  26. void GetAttribute(Info& info, IR::Attribute attribute) {
  27. if (IR::IsGeneric(attribute)) {
  28. info.input_generics.at(IR::GenericAttributeIndex(attribute)).used = true;
  29. return;
  30. }
  31. switch (attribute) {
  32. case IR::Attribute::PositionX:
  33. case IR::Attribute::PositionY:
  34. case IR::Attribute::PositionZ:
  35. case IR::Attribute::PositionW:
  36. info.loads_position = true;
  37. break;
  38. case IR::Attribute::InstanceId:
  39. info.loads_instance_id = true;
  40. break;
  41. case IR::Attribute::VertexId:
  42. info.loads_vertex_id = true;
  43. break;
  44. case IR::Attribute::FrontFace:
  45. info.loads_front_face = true;
  46. break;
  47. case IR::Attribute::PointSpriteS:
  48. case IR::Attribute::PointSpriteT:
  49. info.loads_point_coord = true;
  50. break;
  51. default:
  52. throw NotImplementedException("Get attribute {}", attribute);
  53. }
  54. }
  55. void SetAttribute(Info& info, IR::Attribute attribute) {
  56. if (IR::IsGeneric(attribute)) {
  57. info.stores_generics.at(IR::GenericAttributeIndex(attribute)) = true;
  58. return;
  59. }
  60. switch (attribute) {
  61. case IR::Attribute::PointSize:
  62. info.stores_point_size = true;
  63. break;
  64. case IR::Attribute::PositionX:
  65. case IR::Attribute::PositionY:
  66. case IR::Attribute::PositionZ:
  67. case IR::Attribute::PositionW:
  68. info.stores_position = true;
  69. break;
  70. case IR::Attribute::ClipDistance0:
  71. case IR::Attribute::ClipDistance1:
  72. case IR::Attribute::ClipDistance2:
  73. case IR::Attribute::ClipDistance3:
  74. case IR::Attribute::ClipDistance4:
  75. case IR::Attribute::ClipDistance5:
  76. case IR::Attribute::ClipDistance6:
  77. case IR::Attribute::ClipDistance7:
  78. info.stores_clip_distance = true;
  79. break;
  80. case IR::Attribute::ViewportIndex:
  81. info.stores_viewport_index = true;
  82. break;
  83. default:
  84. throw NotImplementedException("Set attribute {}", attribute);
  85. }
  86. }
  87. void VisitUsages(Info& info, IR::Inst& inst) {
  88. switch (inst.Opcode()) {
  89. case IR::Opcode::CompositeConstructF16x2:
  90. case IR::Opcode::CompositeConstructF16x3:
  91. case IR::Opcode::CompositeConstructF16x4:
  92. case IR::Opcode::CompositeExtractF16x2:
  93. case IR::Opcode::CompositeExtractF16x3:
  94. case IR::Opcode::CompositeExtractF16x4:
  95. case IR::Opcode::CompositeInsertF16x2:
  96. case IR::Opcode::CompositeInsertF16x3:
  97. case IR::Opcode::CompositeInsertF16x4:
  98. case IR::Opcode::SelectF16:
  99. case IR::Opcode::BitCastU16F16:
  100. case IR::Opcode::BitCastF16U16:
  101. case IR::Opcode::PackFloat2x16:
  102. case IR::Opcode::UnpackFloat2x16:
  103. case IR::Opcode::ConvertS16F16:
  104. case IR::Opcode::ConvertS32F16:
  105. case IR::Opcode::ConvertS64F16:
  106. case IR::Opcode::ConvertU16F16:
  107. case IR::Opcode::ConvertU32F16:
  108. case IR::Opcode::ConvertU64F16:
  109. case IR::Opcode::ConvertF16S8:
  110. case IR::Opcode::ConvertF16S16:
  111. case IR::Opcode::ConvertF16S32:
  112. case IR::Opcode::ConvertF16S64:
  113. case IR::Opcode::ConvertF16U8:
  114. case IR::Opcode::ConvertF16U16:
  115. case IR::Opcode::ConvertF16U32:
  116. case IR::Opcode::ConvertF16U64:
  117. case IR::Opcode::FPAbs16:
  118. case IR::Opcode::FPAdd16:
  119. case IR::Opcode::FPCeil16:
  120. case IR::Opcode::FPFloor16:
  121. case IR::Opcode::FPFma16:
  122. case IR::Opcode::FPMul16:
  123. case IR::Opcode::FPNeg16:
  124. case IR::Opcode::FPRoundEven16:
  125. case IR::Opcode::FPSaturate16:
  126. case IR::Opcode::FPClamp16:
  127. case IR::Opcode::FPTrunc16:
  128. case IR::Opcode::FPOrdEqual16:
  129. case IR::Opcode::FPUnordEqual16:
  130. case IR::Opcode::FPOrdNotEqual16:
  131. case IR::Opcode::FPUnordNotEqual16:
  132. case IR::Opcode::FPOrdLessThan16:
  133. case IR::Opcode::FPUnordLessThan16:
  134. case IR::Opcode::FPOrdGreaterThan16:
  135. case IR::Opcode::FPUnordGreaterThan16:
  136. case IR::Opcode::FPOrdLessThanEqual16:
  137. case IR::Opcode::FPUnordLessThanEqual16:
  138. case IR::Opcode::FPOrdGreaterThanEqual16:
  139. case IR::Opcode::FPUnordGreaterThanEqual16:
  140. case IR::Opcode::FPIsNan16:
  141. info.uses_fp16 = true;
  142. break;
  143. case IR::Opcode::CompositeConstructF64x2:
  144. case IR::Opcode::CompositeConstructF64x3:
  145. case IR::Opcode::CompositeConstructF64x4:
  146. case IR::Opcode::CompositeExtractF64x2:
  147. case IR::Opcode::CompositeExtractF64x3:
  148. case IR::Opcode::CompositeExtractF64x4:
  149. case IR::Opcode::CompositeInsertF64x2:
  150. case IR::Opcode::CompositeInsertF64x3:
  151. case IR::Opcode::CompositeInsertF64x4:
  152. case IR::Opcode::SelectF64:
  153. case IR::Opcode::BitCastU64F64:
  154. case IR::Opcode::BitCastF64U64:
  155. case IR::Opcode::PackDouble2x32:
  156. case IR::Opcode::UnpackDouble2x32:
  157. case IR::Opcode::FPAbs64:
  158. case IR::Opcode::FPAdd64:
  159. case IR::Opcode::FPCeil64:
  160. case IR::Opcode::FPFloor64:
  161. case IR::Opcode::FPFma64:
  162. case IR::Opcode::FPMax64:
  163. case IR::Opcode::FPMin64:
  164. case IR::Opcode::FPMul64:
  165. case IR::Opcode::FPNeg64:
  166. case IR::Opcode::FPRecip64:
  167. case IR::Opcode::FPRecipSqrt64:
  168. case IR::Opcode::FPRoundEven64:
  169. case IR::Opcode::FPSaturate64:
  170. case IR::Opcode::FPClamp64:
  171. case IR::Opcode::FPTrunc64:
  172. case IR::Opcode::FPOrdEqual64:
  173. case IR::Opcode::FPUnordEqual64:
  174. case IR::Opcode::FPOrdNotEqual64:
  175. case IR::Opcode::FPUnordNotEqual64:
  176. case IR::Opcode::FPOrdLessThan64:
  177. case IR::Opcode::FPUnordLessThan64:
  178. case IR::Opcode::FPOrdGreaterThan64:
  179. case IR::Opcode::FPUnordGreaterThan64:
  180. case IR::Opcode::FPOrdLessThanEqual64:
  181. case IR::Opcode::FPUnordLessThanEqual64:
  182. case IR::Opcode::FPOrdGreaterThanEqual64:
  183. case IR::Opcode::FPUnordGreaterThanEqual64:
  184. case IR::Opcode::FPIsNan64:
  185. case IR::Opcode::ConvertS16F64:
  186. case IR::Opcode::ConvertS32F64:
  187. case IR::Opcode::ConvertS64F64:
  188. case IR::Opcode::ConvertU16F64:
  189. case IR::Opcode::ConvertU32F64:
  190. case IR::Opcode::ConvertU64F64:
  191. case IR::Opcode::ConvertF32F64:
  192. case IR::Opcode::ConvertF64F32:
  193. case IR::Opcode::ConvertF64S8:
  194. case IR::Opcode::ConvertF64S16:
  195. case IR::Opcode::ConvertF64S32:
  196. case IR::Opcode::ConvertF64S64:
  197. case IR::Opcode::ConvertF64U8:
  198. case IR::Opcode::ConvertF64U16:
  199. case IR::Opcode::ConvertF64U32:
  200. case IR::Opcode::ConvertF64U64:
  201. info.uses_fp64 = true;
  202. break;
  203. default:
  204. break;
  205. }
  206. switch (inst.Opcode()) {
  207. case IR::Opcode::GetCbufU8:
  208. case IR::Opcode::GetCbufS8:
  209. case IR::Opcode::UndefU8:
  210. case IR::Opcode::LoadGlobalU8:
  211. case IR::Opcode::LoadGlobalS8:
  212. case IR::Opcode::WriteGlobalU8:
  213. case IR::Opcode::WriteGlobalS8:
  214. case IR::Opcode::LoadStorageU8:
  215. case IR::Opcode::LoadStorageS8:
  216. case IR::Opcode::WriteStorageU8:
  217. case IR::Opcode::WriteStorageS8:
  218. case IR::Opcode::LoadSharedU8:
  219. case IR::Opcode::LoadSharedS8:
  220. case IR::Opcode::WriteSharedU8:
  221. case IR::Opcode::SelectU8:
  222. case IR::Opcode::ConvertF16S8:
  223. case IR::Opcode::ConvertF16U8:
  224. case IR::Opcode::ConvertF32S8:
  225. case IR::Opcode::ConvertF32U8:
  226. case IR::Opcode::ConvertF64S8:
  227. case IR::Opcode::ConvertF64U8:
  228. info.uses_int8 = true;
  229. break;
  230. default:
  231. break;
  232. }
  233. switch (inst.Opcode()) {
  234. case IR::Opcode::GetCbufU16:
  235. case IR::Opcode::GetCbufS16:
  236. case IR::Opcode::UndefU16:
  237. case IR::Opcode::LoadGlobalU16:
  238. case IR::Opcode::LoadGlobalS16:
  239. case IR::Opcode::WriteGlobalU16:
  240. case IR::Opcode::WriteGlobalS16:
  241. case IR::Opcode::LoadStorageU16:
  242. case IR::Opcode::LoadStorageS16:
  243. case IR::Opcode::WriteStorageU16:
  244. case IR::Opcode::WriteStorageS16:
  245. case IR::Opcode::LoadSharedU16:
  246. case IR::Opcode::LoadSharedS16:
  247. case IR::Opcode::WriteSharedU16:
  248. case IR::Opcode::SelectU16:
  249. case IR::Opcode::BitCastU16F16:
  250. case IR::Opcode::BitCastF16U16:
  251. case IR::Opcode::ConvertS16F16:
  252. case IR::Opcode::ConvertS16F32:
  253. case IR::Opcode::ConvertS16F64:
  254. case IR::Opcode::ConvertU16F16:
  255. case IR::Opcode::ConvertU16F32:
  256. case IR::Opcode::ConvertU16F64:
  257. case IR::Opcode::ConvertF16S16:
  258. case IR::Opcode::ConvertF16U16:
  259. case IR::Opcode::ConvertF32S16:
  260. case IR::Opcode::ConvertF32U16:
  261. case IR::Opcode::ConvertF64S16:
  262. case IR::Opcode::ConvertF64U16:
  263. info.uses_int16 = true;
  264. break;
  265. default:
  266. break;
  267. }
  268. switch (inst.Opcode()) {
  269. case IR::Opcode::UndefU64:
  270. case IR::Opcode::LoadGlobalU8:
  271. case IR::Opcode::LoadGlobalS8:
  272. case IR::Opcode::LoadGlobalU16:
  273. case IR::Opcode::LoadGlobalS16:
  274. case IR::Opcode::LoadGlobal32:
  275. case IR::Opcode::LoadGlobal64:
  276. case IR::Opcode::LoadGlobal128:
  277. case IR::Opcode::WriteGlobalU8:
  278. case IR::Opcode::WriteGlobalS8:
  279. case IR::Opcode::WriteGlobalU16:
  280. case IR::Opcode::WriteGlobalS16:
  281. case IR::Opcode::WriteGlobal32:
  282. case IR::Opcode::WriteGlobal64:
  283. case IR::Opcode::WriteGlobal128:
  284. case IR::Opcode::SelectU64:
  285. case IR::Opcode::BitCastU64F64:
  286. case IR::Opcode::BitCastF64U64:
  287. case IR::Opcode::PackUint2x32:
  288. case IR::Opcode::UnpackUint2x32:
  289. case IR::Opcode::IAdd64:
  290. case IR::Opcode::ISub64:
  291. case IR::Opcode::INeg64:
  292. case IR::Opcode::ShiftLeftLogical64:
  293. case IR::Opcode::ShiftRightLogical64:
  294. case IR::Opcode::ShiftRightArithmetic64:
  295. case IR::Opcode::ConvertS64F16:
  296. case IR::Opcode::ConvertS64F32:
  297. case IR::Opcode::ConvertS64F64:
  298. case IR::Opcode::ConvertU64F16:
  299. case IR::Opcode::ConvertU64F32:
  300. case IR::Opcode::ConvertU64F64:
  301. case IR::Opcode::ConvertU64U32:
  302. case IR::Opcode::ConvertU32U64:
  303. case IR::Opcode::ConvertF16U64:
  304. case IR::Opcode::ConvertF32U64:
  305. case IR::Opcode::ConvertF64U64:
  306. info.uses_int64 = true;
  307. break;
  308. default:
  309. break;
  310. }
  311. switch (inst.Opcode()) {
  312. case IR::Opcode::DemoteToHelperInvocation:
  313. info.uses_demote_to_helper_invocation = true;
  314. break;
  315. case IR::Opcode::GetAttribute:
  316. GetAttribute(info, inst.Arg(0).Attribute());
  317. break;
  318. case IR::Opcode::SetAttribute:
  319. SetAttribute(info, inst.Arg(0).Attribute());
  320. break;
  321. case IR::Opcode::GetAttributeIndexed:
  322. info.loads_indexed_attributes = true;
  323. break;
  324. case IR::Opcode::SetAttributeIndexed:
  325. info.stores_indexed_attributes = true;
  326. break;
  327. case IR::Opcode::SetFragColor:
  328. info.stores_frag_color[inst.Arg(0).U32()] = true;
  329. break;
  330. case IR::Opcode::SetFragDepth:
  331. info.stores_frag_depth = true;
  332. break;
  333. case IR::Opcode::WorkgroupId:
  334. info.uses_workgroup_id = true;
  335. break;
  336. case IR::Opcode::LocalInvocationId:
  337. info.uses_local_invocation_id = true;
  338. break;
  339. case IR::Opcode::ShuffleIndex:
  340. case IR::Opcode::ShuffleUp:
  341. case IR::Opcode::ShuffleDown:
  342. case IR::Opcode::ShuffleButterfly:
  343. case IR::Opcode::LaneId:
  344. info.uses_subgroup_invocation_id = true;
  345. break;
  346. case IR::Opcode::GetCbufU8:
  347. case IR::Opcode::GetCbufS8:
  348. case IR::Opcode::GetCbufU16:
  349. case IR::Opcode::GetCbufS16:
  350. case IR::Opcode::GetCbufU32:
  351. case IR::Opcode::GetCbufF32:
  352. case IR::Opcode::GetCbufU32x2: {
  353. if (const IR::Value index{inst.Arg(0)}; index.IsImmediate()) {
  354. AddConstantBufferDescriptor(info, index.U32(), 1);
  355. } else {
  356. throw NotImplementedException("Constant buffer with non-immediate index");
  357. }
  358. switch (inst.Opcode()) {
  359. case IR::Opcode::GetCbufU8:
  360. case IR::Opcode::GetCbufS8:
  361. info.used_constant_buffer_types |= IR::Type::U8;
  362. break;
  363. case IR::Opcode::GetCbufU16:
  364. case IR::Opcode::GetCbufS16:
  365. info.used_constant_buffer_types |= IR::Type::U16;
  366. break;
  367. case IR::Opcode::GetCbufU32:
  368. info.used_constant_buffer_types |= IR::Type::U32;
  369. break;
  370. case IR::Opcode::GetCbufF32:
  371. info.used_constant_buffer_types |= IR::Type::F32;
  372. break;
  373. case IR::Opcode::GetCbufU32x2:
  374. info.used_constant_buffer_types |= IR::Type::U32x2;
  375. break;
  376. default:
  377. break;
  378. }
  379. break;
  380. }
  381. case IR::Opcode::BindlessImageSampleImplicitLod:
  382. case IR::Opcode::BindlessImageSampleExplicitLod:
  383. case IR::Opcode::BindlessImageSampleDrefImplicitLod:
  384. case IR::Opcode::BindlessImageSampleDrefExplicitLod:
  385. case IR::Opcode::BindlessImageGather:
  386. case IR::Opcode::BindlessImageGatherDref:
  387. case IR::Opcode::BindlessImageFetch:
  388. case IR::Opcode::BindlessImageQueryDimensions:
  389. case IR::Opcode::BindlessImageQueryLod:
  390. case IR::Opcode::BindlessImageGradient:
  391. case IR::Opcode::BoundImageSampleImplicitLod:
  392. case IR::Opcode::BoundImageSampleExplicitLod:
  393. case IR::Opcode::BoundImageSampleDrefImplicitLod:
  394. case IR::Opcode::BoundImageSampleDrefExplicitLod:
  395. case IR::Opcode::BoundImageGather:
  396. case IR::Opcode::BoundImageGatherDref:
  397. case IR::Opcode::BoundImageFetch:
  398. case IR::Opcode::BoundImageQueryDimensions:
  399. case IR::Opcode::BoundImageQueryLod:
  400. case IR::Opcode::BoundImageGradient:
  401. case IR::Opcode::ImageSampleImplicitLod:
  402. case IR::Opcode::ImageSampleExplicitLod:
  403. case IR::Opcode::ImageSampleDrefImplicitLod:
  404. case IR::Opcode::ImageSampleDrefExplicitLod:
  405. case IR::Opcode::ImageGather:
  406. case IR::Opcode::ImageGatherDref:
  407. case IR::Opcode::ImageFetch:
  408. case IR::Opcode::ImageQueryDimensions:
  409. case IR::Opcode::ImageQueryLod:
  410. case IR::Opcode::ImageGradient: {
  411. const TextureType type{inst.Flags<IR::TextureInstInfo>().type};
  412. info.uses_sampled_1d |= type == TextureType::Color1D || type == TextureType::ColorArray1D ||
  413. type == TextureType::Shadow1D || type == TextureType::ShadowArray1D;
  414. info.uses_sparse_residency |=
  415. inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr;
  416. break;
  417. }
  418. case IR::Opcode::SubgroupEqMask:
  419. case IR::Opcode::SubgroupLtMask:
  420. case IR::Opcode::SubgroupLeMask:
  421. case IR::Opcode::SubgroupGtMask:
  422. case IR::Opcode::SubgroupGeMask:
  423. info.uses_subgroup_mask = true;
  424. break;
  425. case IR::Opcode::VoteAll:
  426. case IR::Opcode::VoteAny:
  427. case IR::Opcode::VoteEqual:
  428. case IR::Opcode::SubgroupBallot:
  429. info.uses_subgroup_vote = true;
  430. break;
  431. case IR::Opcode::FSwizzleAdd:
  432. info.uses_fswzadd = true;
  433. break;
  434. default:
  435. break;
  436. }
  437. }
  438. void VisitFpModifiers(Info& info, IR::Inst& inst) {
  439. switch (inst.Opcode()) {
  440. case IR::Opcode::FPAdd16:
  441. case IR::Opcode::FPFma16:
  442. case IR::Opcode::FPMul16:
  443. case IR::Opcode::FPRoundEven16:
  444. case IR::Opcode::FPFloor16:
  445. case IR::Opcode::FPCeil16:
  446. case IR::Opcode::FPTrunc16: {
  447. const auto control{inst.Flags<IR::FpControl>()};
  448. switch (control.fmz_mode) {
  449. case IR::FmzMode::DontCare:
  450. break;
  451. case IR::FmzMode::FTZ:
  452. case IR::FmzMode::FMZ:
  453. info.uses_fp16_denorms_flush = true;
  454. break;
  455. case IR::FmzMode::None:
  456. info.uses_fp16_denorms_preserve = true;
  457. break;
  458. }
  459. break;
  460. }
  461. case IR::Opcode::FPAdd32:
  462. case IR::Opcode::FPFma32:
  463. case IR::Opcode::FPMul32:
  464. case IR::Opcode::FPRoundEven32:
  465. case IR::Opcode::FPFloor32:
  466. case IR::Opcode::FPCeil32:
  467. case IR::Opcode::FPTrunc32:
  468. case IR::Opcode::FPOrdEqual32:
  469. case IR::Opcode::FPUnordEqual32:
  470. case IR::Opcode::FPOrdNotEqual32:
  471. case IR::Opcode::FPUnordNotEqual32:
  472. case IR::Opcode::FPOrdLessThan32:
  473. case IR::Opcode::FPUnordLessThan32:
  474. case IR::Opcode::FPOrdGreaterThan32:
  475. case IR::Opcode::FPUnordGreaterThan32:
  476. case IR::Opcode::FPOrdLessThanEqual32:
  477. case IR::Opcode::FPUnordLessThanEqual32:
  478. case IR::Opcode::FPOrdGreaterThanEqual32:
  479. case IR::Opcode::FPUnordGreaterThanEqual32:
  480. case IR::Opcode::ConvertF16F32:
  481. case IR::Opcode::ConvertF64F32: {
  482. const auto control{inst.Flags<IR::FpControl>()};
  483. switch (control.fmz_mode) {
  484. case IR::FmzMode::DontCare:
  485. break;
  486. case IR::FmzMode::FTZ:
  487. case IR::FmzMode::FMZ:
  488. info.uses_fp32_denorms_flush = true;
  489. break;
  490. case IR::FmzMode::None:
  491. info.uses_fp32_denorms_preserve = true;
  492. break;
  493. }
  494. break;
  495. }
  496. default:
  497. break;
  498. }
  499. }
  500. void Visit(Info& info, IR::Inst& inst) {
  501. VisitUsages(info, inst);
  502. VisitFpModifiers(info, inst);
  503. }
  504. void GatherInfoFromHeader(Environment& env, Info& info) {
  505. auto stage = env.ShaderStage();
  506. if (stage == Stage::Compute) {
  507. return;
  508. }
  509. const auto& header = env.SPH();
  510. if (stage == Stage::Fragment) {
  511. if (!info.loads_indexed_attributes) {
  512. return;
  513. }
  514. for (size_t i = 0; i < info.input_generics.size(); i++) {
  515. info.input_generics[i].used =
  516. info.input_generics[i].used || header.ps.IsGenericVectorActive(i);
  517. }
  518. info.loads_position = info.loads_position || header.ps.imap_systemb.position != 0;
  519. return;
  520. }
  521. if (info.loads_indexed_attributes) {
  522. for (size_t i = 0; i < info.input_generics.size(); i++) {
  523. info.input_generics[i].used =
  524. info.input_generics[i].used || header.vtg.IsInputGenericVectorActive(i);
  525. }
  526. }
  527. if (info.stores_indexed_attributes) {
  528. info.loads_position = info.loads_position || header.vtg.imap_systemb.position != 0;
  529. for (size_t i = 0; i < info.stores_generics.size(); i++) {
  530. info.stores_generics[i] =
  531. info.stores_generics[i] || header.vtg.IsOutputGenericVectorActive(i);
  532. }
  533. info.stores_clip_distance =
  534. info.stores_clip_distance || header.vtg.omap_systemc.clip_distances != 0;
  535. info.stores_position = info.stores_position || header.vtg.omap_systemb.position != 0;
  536. }
  537. }
  538. } // Anonymous namespace
  539. void CollectShaderInfoPass(Environment& env, IR::Program& program) {
  540. Info& info{program.info};
  541. for (IR::Block* const block : program.post_order_blocks) {
  542. for (IR::Inst& inst : block->Instructions()) {
  543. Visit(info, inst);
  544. }
  545. }
  546. GatherInfoFromHeader(env, info);
  547. }
  548. } // namespace Shader::Optimization