collect_shader_info_pass.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/alignment.h"
  5. #include "shader_recompiler/environment.h"
  6. #include "shader_recompiler/frontend/ir/modifiers.h"
  7. #include "shader_recompiler/frontend/ir/program.h"
  8. #include "shader_recompiler/frontend/ir/value.h"
  9. #include "shader_recompiler/ir_opt/passes.h"
  10. #include "shader_recompiler/shader_info.h"
  11. namespace Shader::Optimization {
  12. namespace {
  13. void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) {
  14. if (count != 1) {
  15. throw NotImplementedException("Constant buffer descriptor indexing");
  16. }
  17. if ((info.constant_buffer_mask & (1U << index)) != 0) {
  18. return;
  19. }
  20. info.constant_buffer_mask |= 1U << index;
  21. auto& cbufs{info.constant_buffer_descriptors};
  22. cbufs.insert(std::ranges::lower_bound(cbufs, index, {}, &ConstantBufferDescriptor::index),
  23. ConstantBufferDescriptor{
  24. .index = index,
  25. .count = 1,
  26. });
  27. }
  28. void AddRegisterIndexedLdc(Info& info) {
  29. info.uses_cbuf_indirect = true;
  30. // The shader can use any possible constant buffer
  31. info.constant_buffer_mask = (1 << Info::MAX_CBUFS) - 1;
  32. auto& cbufs{info.constant_buffer_descriptors};
  33. cbufs.clear();
  34. for (u32 i = 0; i < Info::MAX_CBUFS; i++) {
  35. cbufs.push_back(ConstantBufferDescriptor{.index = i, .count = 1});
  36. // The shader can use any possible access size
  37. info.constant_buffer_used_sizes[i] = 0x10'000;
  38. }
  39. }
  40. void GetPatch(Info& info, IR::Patch patch) {
  41. if (!IR::IsGeneric(patch)) {
  42. throw NotImplementedException("Reading non-generic patch {}", patch);
  43. }
  44. info.uses_patches.at(IR::GenericPatchIndex(patch)) = true;
  45. }
  46. void SetPatch(Info& info, IR::Patch patch) {
  47. if (IR::IsGeneric(patch)) {
  48. info.uses_patches.at(IR::GenericPatchIndex(patch)) = true;
  49. return;
  50. }
  51. switch (patch) {
  52. case IR::Patch::TessellationLodLeft:
  53. case IR::Patch::TessellationLodTop:
  54. case IR::Patch::TessellationLodRight:
  55. case IR::Patch::TessellationLodBottom:
  56. info.stores_tess_level_outer = true;
  57. break;
  58. case IR::Patch::TessellationLodInteriorU:
  59. case IR::Patch::TessellationLodInteriorV:
  60. info.stores_tess_level_inner = true;
  61. break;
  62. default:
  63. throw NotImplementedException("Set patch {}", patch);
  64. }
  65. }
  66. void CheckCBufNVN(Info& info, IR::Inst& inst) {
  67. const IR::Value cbuf_index{inst.Arg(0)};
  68. if (!cbuf_index.IsImmediate()) {
  69. info.nvn_buffer_used.set();
  70. return;
  71. }
  72. const u32 index{cbuf_index.U32()};
  73. if (index != 0) {
  74. return;
  75. }
  76. const IR::Value cbuf_offset{inst.Arg(1)};
  77. if (!cbuf_offset.IsImmediate()) {
  78. info.nvn_buffer_used.set();
  79. return;
  80. }
  81. const u32 offset{cbuf_offset.U32()};
  82. const u32 descriptor_size{0x10};
  83. const u32 upper_limit{info.nvn_buffer_base + descriptor_size * 16};
  84. if (offset >= info.nvn_buffer_base && offset < upper_limit) {
  85. const std::size_t nvn_index{(offset - info.nvn_buffer_base) / descriptor_size};
  86. info.nvn_buffer_used.set(nvn_index, true);
  87. }
  88. }
  89. void VisitUsages(Info& info, IR::Inst& inst) {
  90. switch (inst.GetOpcode()) {
  91. case IR::Opcode::CompositeConstructF16x2:
  92. case IR::Opcode::CompositeConstructF16x3:
  93. case IR::Opcode::CompositeConstructF16x4:
  94. case IR::Opcode::CompositeExtractF16x2:
  95. case IR::Opcode::CompositeExtractF16x3:
  96. case IR::Opcode::CompositeExtractF16x4:
  97. case IR::Opcode::CompositeInsertF16x2:
  98. case IR::Opcode::CompositeInsertF16x3:
  99. case IR::Opcode::CompositeInsertF16x4:
  100. case IR::Opcode::SelectF16:
  101. case IR::Opcode::BitCastU16F16:
  102. case IR::Opcode::BitCastF16U16:
  103. case IR::Opcode::PackFloat2x16:
  104. case IR::Opcode::UnpackFloat2x16:
  105. case IR::Opcode::ConvertS16F16:
  106. case IR::Opcode::ConvertS32F16:
  107. case IR::Opcode::ConvertS64F16:
  108. case IR::Opcode::ConvertU16F16:
  109. case IR::Opcode::ConvertU32F16:
  110. case IR::Opcode::ConvertU64F16:
  111. case IR::Opcode::ConvertF16S8:
  112. case IR::Opcode::ConvertF16S16:
  113. case IR::Opcode::ConvertF16S32:
  114. case IR::Opcode::ConvertF16S64:
  115. case IR::Opcode::ConvertF16U8:
  116. case IR::Opcode::ConvertF16U16:
  117. case IR::Opcode::ConvertF16U32:
  118. case IR::Opcode::ConvertF16U64:
  119. case IR::Opcode::ConvertF16F32:
  120. case IR::Opcode::ConvertF32F16:
  121. case IR::Opcode::FPAbs16:
  122. case IR::Opcode::FPAdd16:
  123. case IR::Opcode::FPCeil16:
  124. case IR::Opcode::FPFloor16:
  125. case IR::Opcode::FPFma16:
  126. case IR::Opcode::FPMul16:
  127. case IR::Opcode::FPNeg16:
  128. case IR::Opcode::FPRoundEven16:
  129. case IR::Opcode::FPSaturate16:
  130. case IR::Opcode::FPClamp16:
  131. case IR::Opcode::FPTrunc16:
  132. case IR::Opcode::FPOrdEqual16:
  133. case IR::Opcode::FPUnordEqual16:
  134. case IR::Opcode::FPOrdNotEqual16:
  135. case IR::Opcode::FPUnordNotEqual16:
  136. case IR::Opcode::FPOrdLessThan16:
  137. case IR::Opcode::FPUnordLessThan16:
  138. case IR::Opcode::FPOrdGreaterThan16:
  139. case IR::Opcode::FPUnordGreaterThan16:
  140. case IR::Opcode::FPOrdLessThanEqual16:
  141. case IR::Opcode::FPUnordLessThanEqual16:
  142. case IR::Opcode::FPOrdGreaterThanEqual16:
  143. case IR::Opcode::FPUnordGreaterThanEqual16:
  144. case IR::Opcode::FPIsNan16:
  145. case IR::Opcode::GlobalAtomicAddF16x2:
  146. case IR::Opcode::GlobalAtomicMinF16x2:
  147. case IR::Opcode::GlobalAtomicMaxF16x2:
  148. case IR::Opcode::StorageAtomicAddF16x2:
  149. case IR::Opcode::StorageAtomicMinF16x2:
  150. case IR::Opcode::StorageAtomicMaxF16x2:
  151. info.uses_fp16 = true;
  152. break;
  153. case IR::Opcode::CompositeConstructF64x2:
  154. case IR::Opcode::CompositeConstructF64x3:
  155. case IR::Opcode::CompositeConstructF64x4:
  156. case IR::Opcode::CompositeExtractF64x2:
  157. case IR::Opcode::CompositeExtractF64x3:
  158. case IR::Opcode::CompositeExtractF64x4:
  159. case IR::Opcode::CompositeInsertF64x2:
  160. case IR::Opcode::CompositeInsertF64x3:
  161. case IR::Opcode::CompositeInsertF64x4:
  162. case IR::Opcode::SelectF64:
  163. case IR::Opcode::BitCastU64F64:
  164. case IR::Opcode::BitCastF64U64:
  165. case IR::Opcode::PackDouble2x32:
  166. case IR::Opcode::UnpackDouble2x32:
  167. case IR::Opcode::FPAbs64:
  168. case IR::Opcode::FPAdd64:
  169. case IR::Opcode::FPCeil64:
  170. case IR::Opcode::FPFloor64:
  171. case IR::Opcode::FPFma64:
  172. case IR::Opcode::FPMax64:
  173. case IR::Opcode::FPMin64:
  174. case IR::Opcode::FPMul64:
  175. case IR::Opcode::FPNeg64:
  176. case IR::Opcode::FPRecip64:
  177. case IR::Opcode::FPRecipSqrt64:
  178. case IR::Opcode::FPRoundEven64:
  179. case IR::Opcode::FPSaturate64:
  180. case IR::Opcode::FPClamp64:
  181. case IR::Opcode::FPTrunc64:
  182. case IR::Opcode::FPOrdEqual64:
  183. case IR::Opcode::FPUnordEqual64:
  184. case IR::Opcode::FPOrdNotEqual64:
  185. case IR::Opcode::FPUnordNotEqual64:
  186. case IR::Opcode::FPOrdLessThan64:
  187. case IR::Opcode::FPUnordLessThan64:
  188. case IR::Opcode::FPOrdGreaterThan64:
  189. case IR::Opcode::FPUnordGreaterThan64:
  190. case IR::Opcode::FPOrdLessThanEqual64:
  191. case IR::Opcode::FPUnordLessThanEqual64:
  192. case IR::Opcode::FPOrdGreaterThanEqual64:
  193. case IR::Opcode::FPUnordGreaterThanEqual64:
  194. case IR::Opcode::FPIsNan64:
  195. case IR::Opcode::ConvertS16F64:
  196. case IR::Opcode::ConvertS32F64:
  197. case IR::Opcode::ConvertS64F64:
  198. case IR::Opcode::ConvertU16F64:
  199. case IR::Opcode::ConvertU32F64:
  200. case IR::Opcode::ConvertU64F64:
  201. case IR::Opcode::ConvertF32F64:
  202. case IR::Opcode::ConvertF64F32:
  203. case IR::Opcode::ConvertF64S8:
  204. case IR::Opcode::ConvertF64S16:
  205. case IR::Opcode::ConvertF64S32:
  206. case IR::Opcode::ConvertF64S64:
  207. case IR::Opcode::ConvertF64U8:
  208. case IR::Opcode::ConvertF64U16:
  209. case IR::Opcode::ConvertF64U32:
  210. case IR::Opcode::ConvertF64U64:
  211. info.uses_fp64 = true;
  212. break;
  213. default:
  214. break;
  215. }
  216. switch (inst.GetOpcode()) {
  217. case IR::Opcode::GetCbufU8:
  218. case IR::Opcode::GetCbufS8:
  219. case IR::Opcode::UndefU8:
  220. case IR::Opcode::LoadGlobalU8:
  221. case IR::Opcode::LoadGlobalS8:
  222. case IR::Opcode::WriteGlobalU8:
  223. case IR::Opcode::WriteGlobalS8:
  224. case IR::Opcode::LoadStorageU8:
  225. case IR::Opcode::LoadStorageS8:
  226. case IR::Opcode::WriteStorageU8:
  227. case IR::Opcode::WriteStorageS8:
  228. case IR::Opcode::LoadSharedU8:
  229. case IR::Opcode::LoadSharedS8:
  230. case IR::Opcode::WriteSharedU8:
  231. case IR::Opcode::SelectU8:
  232. case IR::Opcode::ConvertF16S8:
  233. case IR::Opcode::ConvertF16U8:
  234. case IR::Opcode::ConvertF32S8:
  235. case IR::Opcode::ConvertF32U8:
  236. case IR::Opcode::ConvertF64S8:
  237. case IR::Opcode::ConvertF64U8:
  238. info.uses_int8 = true;
  239. break;
  240. default:
  241. break;
  242. }
  243. switch (inst.GetOpcode()) {
  244. case IR::Opcode::GetCbufU16:
  245. case IR::Opcode::GetCbufS16:
  246. case IR::Opcode::UndefU16:
  247. case IR::Opcode::LoadGlobalU16:
  248. case IR::Opcode::LoadGlobalS16:
  249. case IR::Opcode::WriteGlobalU16:
  250. case IR::Opcode::WriteGlobalS16:
  251. case IR::Opcode::LoadStorageU16:
  252. case IR::Opcode::LoadStorageS16:
  253. case IR::Opcode::WriteStorageU16:
  254. case IR::Opcode::WriteStorageS16:
  255. case IR::Opcode::LoadSharedU16:
  256. case IR::Opcode::LoadSharedS16:
  257. case IR::Opcode::WriteSharedU16:
  258. case IR::Opcode::SelectU16:
  259. case IR::Opcode::BitCastU16F16:
  260. case IR::Opcode::BitCastF16U16:
  261. case IR::Opcode::ConvertS16F16:
  262. case IR::Opcode::ConvertS16F32:
  263. case IR::Opcode::ConvertS16F64:
  264. case IR::Opcode::ConvertU16F16:
  265. case IR::Opcode::ConvertU16F32:
  266. case IR::Opcode::ConvertU16F64:
  267. case IR::Opcode::ConvertF16S16:
  268. case IR::Opcode::ConvertF16U16:
  269. case IR::Opcode::ConvertF32S16:
  270. case IR::Opcode::ConvertF32U16:
  271. case IR::Opcode::ConvertF64S16:
  272. case IR::Opcode::ConvertF64U16:
  273. info.uses_int16 = true;
  274. break;
  275. default:
  276. break;
  277. }
  278. switch (inst.GetOpcode()) {
  279. case IR::Opcode::UndefU64:
  280. case IR::Opcode::LoadGlobalU8:
  281. case IR::Opcode::LoadGlobalS8:
  282. case IR::Opcode::LoadGlobalU16:
  283. case IR::Opcode::LoadGlobalS16:
  284. case IR::Opcode::LoadGlobal32:
  285. case IR::Opcode::LoadGlobal64:
  286. case IR::Opcode::LoadGlobal128:
  287. case IR::Opcode::WriteGlobalU8:
  288. case IR::Opcode::WriteGlobalS8:
  289. case IR::Opcode::WriteGlobalU16:
  290. case IR::Opcode::WriteGlobalS16:
  291. case IR::Opcode::WriteGlobal32:
  292. case IR::Opcode::WriteGlobal64:
  293. case IR::Opcode::WriteGlobal128:
  294. case IR::Opcode::SelectU64:
  295. case IR::Opcode::BitCastU64F64:
  296. case IR::Opcode::BitCastF64U64:
  297. case IR::Opcode::PackUint2x32:
  298. case IR::Opcode::UnpackUint2x32:
  299. case IR::Opcode::IAdd64:
  300. case IR::Opcode::ISub64:
  301. case IR::Opcode::INeg64:
  302. case IR::Opcode::ShiftLeftLogical64:
  303. case IR::Opcode::ShiftRightLogical64:
  304. case IR::Opcode::ShiftRightArithmetic64:
  305. case IR::Opcode::ConvertS64F16:
  306. case IR::Opcode::ConvertS64F32:
  307. case IR::Opcode::ConvertS64F64:
  308. case IR::Opcode::ConvertU64F16:
  309. case IR::Opcode::ConvertU64F32:
  310. case IR::Opcode::ConvertU64F64:
  311. case IR::Opcode::ConvertU64U32:
  312. case IR::Opcode::ConvertU32U64:
  313. case IR::Opcode::ConvertF16U64:
  314. case IR::Opcode::ConvertF32U64:
  315. case IR::Opcode::ConvertF64U64:
  316. case IR::Opcode::SharedAtomicExchange64:
  317. case IR::Opcode::GlobalAtomicIAdd64:
  318. case IR::Opcode::GlobalAtomicSMin64:
  319. case IR::Opcode::GlobalAtomicUMin64:
  320. case IR::Opcode::GlobalAtomicSMax64:
  321. case IR::Opcode::GlobalAtomicUMax64:
  322. case IR::Opcode::GlobalAtomicAnd64:
  323. case IR::Opcode::GlobalAtomicOr64:
  324. case IR::Opcode::GlobalAtomicXor64:
  325. case IR::Opcode::GlobalAtomicExchange64:
  326. case IR::Opcode::StorageAtomicIAdd64:
  327. case IR::Opcode::StorageAtomicSMin64:
  328. case IR::Opcode::StorageAtomicUMin64:
  329. case IR::Opcode::StorageAtomicSMax64:
  330. case IR::Opcode::StorageAtomicUMax64:
  331. case IR::Opcode::StorageAtomicAnd64:
  332. case IR::Opcode::StorageAtomicOr64:
  333. case IR::Opcode::StorageAtomicXor64:
  334. case IR::Opcode::StorageAtomicExchange64:
  335. info.uses_int64 = true;
  336. break;
  337. default:
  338. break;
  339. }
  340. switch (inst.GetOpcode()) {
  341. case IR::Opcode::WriteGlobalU8:
  342. case IR::Opcode::WriteGlobalS8:
  343. case IR::Opcode::WriteGlobalU16:
  344. case IR::Opcode::WriteGlobalS16:
  345. case IR::Opcode::WriteGlobal32:
  346. case IR::Opcode::WriteGlobal64:
  347. case IR::Opcode::WriteGlobal128:
  348. case IR::Opcode::GlobalAtomicIAdd32:
  349. case IR::Opcode::GlobalAtomicSMin32:
  350. case IR::Opcode::GlobalAtomicUMin32:
  351. case IR::Opcode::GlobalAtomicSMax32:
  352. case IR::Opcode::GlobalAtomicUMax32:
  353. case IR::Opcode::GlobalAtomicInc32:
  354. case IR::Opcode::GlobalAtomicDec32:
  355. case IR::Opcode::GlobalAtomicAnd32:
  356. case IR::Opcode::GlobalAtomicOr32:
  357. case IR::Opcode::GlobalAtomicXor32:
  358. case IR::Opcode::GlobalAtomicExchange32:
  359. case IR::Opcode::GlobalAtomicIAdd64:
  360. case IR::Opcode::GlobalAtomicSMin64:
  361. case IR::Opcode::GlobalAtomicUMin64:
  362. case IR::Opcode::GlobalAtomicSMax64:
  363. case IR::Opcode::GlobalAtomicUMax64:
  364. case IR::Opcode::GlobalAtomicAnd64:
  365. case IR::Opcode::GlobalAtomicOr64:
  366. case IR::Opcode::GlobalAtomicXor64:
  367. case IR::Opcode::GlobalAtomicExchange64:
  368. case IR::Opcode::GlobalAtomicIAdd32x2:
  369. case IR::Opcode::GlobalAtomicSMin32x2:
  370. case IR::Opcode::GlobalAtomicUMin32x2:
  371. case IR::Opcode::GlobalAtomicSMax32x2:
  372. case IR::Opcode::GlobalAtomicUMax32x2:
  373. case IR::Opcode::GlobalAtomicAnd32x2:
  374. case IR::Opcode::GlobalAtomicOr32x2:
  375. case IR::Opcode::GlobalAtomicXor32x2:
  376. case IR::Opcode::GlobalAtomicExchange32x2:
  377. case IR::Opcode::GlobalAtomicAddF32:
  378. case IR::Opcode::GlobalAtomicAddF16x2:
  379. case IR::Opcode::GlobalAtomicAddF32x2:
  380. case IR::Opcode::GlobalAtomicMinF16x2:
  381. case IR::Opcode::GlobalAtomicMinF32x2:
  382. case IR::Opcode::GlobalAtomicMaxF16x2:
  383. case IR::Opcode::GlobalAtomicMaxF32x2:
  384. info.stores_global_memory = true;
  385. [[fallthrough]];
  386. case IR::Opcode::LoadGlobalU8:
  387. case IR::Opcode::LoadGlobalS8:
  388. case IR::Opcode::LoadGlobalU16:
  389. case IR::Opcode::LoadGlobalS16:
  390. case IR::Opcode::LoadGlobal32:
  391. case IR::Opcode::LoadGlobal64:
  392. case IR::Opcode::LoadGlobal128:
  393. info.uses_int64 = true;
  394. info.uses_global_memory = true;
  395. info.used_constant_buffer_types |= IR::Type::U32 | IR::Type::U32x2;
  396. info.used_storage_buffer_types |= IR::Type::U32 | IR::Type::U32x2 | IR::Type::U32x4;
  397. break;
  398. default:
  399. break;
  400. }
  401. switch (inst.GetOpcode()) {
  402. case IR::Opcode::DemoteToHelperInvocation:
  403. info.uses_demote_to_helper_invocation = true;
  404. break;
  405. case IR::Opcode::GetAttribute:
  406. case IR::Opcode::GetAttributeU32:
  407. info.loads.mask[static_cast<size_t>(inst.Arg(0).Attribute())] = true;
  408. break;
  409. case IR::Opcode::SetAttribute:
  410. info.stores.mask[static_cast<size_t>(inst.Arg(0).Attribute())] = true;
  411. break;
  412. case IR::Opcode::GetPatch:
  413. GetPatch(info, inst.Arg(0).Patch());
  414. break;
  415. case IR::Opcode::SetPatch:
  416. SetPatch(info, inst.Arg(0).Patch());
  417. break;
  418. case IR::Opcode::GetAttributeIndexed:
  419. info.loads_indexed_attributes = true;
  420. break;
  421. case IR::Opcode::SetAttributeIndexed:
  422. info.stores_indexed_attributes = true;
  423. break;
  424. case IR::Opcode::SetFragColor:
  425. info.stores_frag_color[inst.Arg(0).U32()] = true;
  426. break;
  427. case IR::Opcode::SetSampleMask:
  428. info.stores_sample_mask = true;
  429. break;
  430. case IR::Opcode::SetFragDepth:
  431. info.stores_frag_depth = true;
  432. break;
  433. case IR::Opcode::WorkgroupId:
  434. info.uses_workgroup_id = true;
  435. break;
  436. case IR::Opcode::LocalInvocationId:
  437. info.uses_local_invocation_id = true;
  438. break;
  439. case IR::Opcode::InvocationId:
  440. info.uses_invocation_id = true;
  441. break;
  442. case IR::Opcode::SampleId:
  443. info.uses_sample_id = true;
  444. break;
  445. case IR::Opcode::IsHelperInvocation:
  446. info.uses_is_helper_invocation = true;
  447. break;
  448. case IR::Opcode::ResolutionDownFactor:
  449. case IR::Opcode::IsTextureScaled:
  450. case IR::Opcode::IsImageScaled:
  451. info.uses_rescaling_uniform = true;
  452. break;
  453. case IR::Opcode::LaneId:
  454. info.uses_subgroup_invocation_id = true;
  455. break;
  456. case IR::Opcode::ShuffleIndex:
  457. case IR::Opcode::ShuffleUp:
  458. case IR::Opcode::ShuffleDown:
  459. case IR::Opcode::ShuffleButterfly:
  460. info.uses_subgroup_shuffles = true;
  461. break;
  462. case IR::Opcode::GetCbufU8:
  463. case IR::Opcode::GetCbufS8:
  464. case IR::Opcode::GetCbufU16:
  465. case IR::Opcode::GetCbufS16:
  466. case IR::Opcode::GetCbufU32:
  467. case IR::Opcode::GetCbufF32:
  468. case IR::Opcode::GetCbufU32x2: {
  469. const IR::Value index{inst.Arg(0)};
  470. const IR::Value offset{inst.Arg(1)};
  471. if (index.IsImmediate()) {
  472. AddConstantBufferDescriptor(info, index.U32(), 1);
  473. } else {
  474. AddRegisterIndexedLdc(info);
  475. }
  476. u32 element_size{};
  477. switch (inst.GetOpcode()) {
  478. case IR::Opcode::GetCbufU8:
  479. case IR::Opcode::GetCbufS8:
  480. info.used_constant_buffer_types |= IR::Type::U8;
  481. element_size = 1;
  482. break;
  483. case IR::Opcode::GetCbufU16:
  484. case IR::Opcode::GetCbufS16:
  485. info.used_constant_buffer_types |= IR::Type::U16;
  486. element_size = 2;
  487. break;
  488. case IR::Opcode::GetCbufU32:
  489. info.used_constant_buffer_types |= IR::Type::U32;
  490. element_size = 4;
  491. break;
  492. case IR::Opcode::GetCbufF32:
  493. info.used_constant_buffer_types |= IR::Type::F32;
  494. element_size = 4;
  495. break;
  496. case IR::Opcode::GetCbufU32x2:
  497. info.used_constant_buffer_types |= IR::Type::U32x2;
  498. element_size = 8;
  499. break;
  500. default:
  501. break;
  502. }
  503. if (index.IsImmediate()) {
  504. u32& size{info.constant_buffer_used_sizes[index.U32()]};
  505. if (offset.IsImmediate()) {
  506. size = Common::AlignUp(std::max(size, offset.U32() + element_size), 16u);
  507. } else {
  508. size = 0x10'000;
  509. }
  510. }
  511. break;
  512. }
  513. case IR::Opcode::BindlessImageSampleImplicitLod:
  514. case IR::Opcode::BindlessImageSampleExplicitLod:
  515. case IR::Opcode::BindlessImageSampleDrefImplicitLod:
  516. case IR::Opcode::BindlessImageSampleDrefExplicitLod:
  517. case IR::Opcode::BindlessImageGather:
  518. case IR::Opcode::BindlessImageGatherDref:
  519. case IR::Opcode::BindlessImageFetch:
  520. case IR::Opcode::BindlessImageQueryDimensions:
  521. case IR::Opcode::BindlessImageQueryLod:
  522. case IR::Opcode::BindlessImageGradient:
  523. case IR::Opcode::BoundImageSampleImplicitLod:
  524. case IR::Opcode::BoundImageSampleExplicitLod:
  525. case IR::Opcode::BoundImageSampleDrefImplicitLod:
  526. case IR::Opcode::BoundImageSampleDrefExplicitLod:
  527. case IR::Opcode::BoundImageGather:
  528. case IR::Opcode::BoundImageGatherDref:
  529. case IR::Opcode::BoundImageFetch:
  530. case IR::Opcode::BoundImageQueryDimensions:
  531. case IR::Opcode::BoundImageQueryLod:
  532. case IR::Opcode::BoundImageGradient:
  533. case IR::Opcode::ImageGather:
  534. case IR::Opcode::ImageGatherDref:
  535. case IR::Opcode::ImageFetch:
  536. case IR::Opcode::ImageQueryDimensions:
  537. case IR::Opcode::ImageGradient: {
  538. const TextureType type{inst.Flags<IR::TextureInstInfo>().type};
  539. info.uses_sampled_1d |= type == TextureType::Color1D || type == TextureType::ColorArray1D;
  540. info.uses_sparse_residency |=
  541. inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr;
  542. break;
  543. }
  544. case IR::Opcode::ImageSampleImplicitLod:
  545. case IR::Opcode::ImageSampleExplicitLod:
  546. case IR::Opcode::ImageSampleDrefImplicitLod:
  547. case IR::Opcode::ImageSampleDrefExplicitLod:
  548. case IR::Opcode::ImageQueryLod: {
  549. const auto flags{inst.Flags<IR::TextureInstInfo>()};
  550. const TextureType type{flags.type};
  551. info.uses_sampled_1d |= type == TextureType::Color1D || type == TextureType::ColorArray1D;
  552. info.uses_shadow_lod |= flags.is_depth != 0;
  553. info.uses_sparse_residency |=
  554. inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr;
  555. break;
  556. }
  557. case IR::Opcode::ImageRead: {
  558. const auto flags{inst.Flags<IR::TextureInstInfo>()};
  559. info.uses_typeless_image_reads |= flags.image_format == ImageFormat::Typeless;
  560. info.uses_sparse_residency |=
  561. inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr;
  562. break;
  563. }
  564. case IR::Opcode::ImageWrite: {
  565. const auto flags{inst.Flags<IR::TextureInstInfo>()};
  566. info.uses_typeless_image_writes |= flags.image_format == ImageFormat::Typeless;
  567. info.uses_image_buffers |= flags.type == TextureType::Buffer;
  568. break;
  569. }
  570. case IR::Opcode::SubgroupEqMask:
  571. case IR::Opcode::SubgroupLtMask:
  572. case IR::Opcode::SubgroupLeMask:
  573. case IR::Opcode::SubgroupGtMask:
  574. case IR::Opcode::SubgroupGeMask:
  575. info.uses_subgroup_mask = true;
  576. break;
  577. case IR::Opcode::VoteAll:
  578. case IR::Opcode::VoteAny:
  579. case IR::Opcode::VoteEqual:
  580. case IR::Opcode::SubgroupBallot:
  581. info.uses_subgroup_vote = true;
  582. break;
  583. case IR::Opcode::FSwizzleAdd:
  584. info.uses_fswzadd = true;
  585. break;
  586. case IR::Opcode::DPdxFine:
  587. case IR::Opcode::DPdyFine:
  588. case IR::Opcode::DPdxCoarse:
  589. case IR::Opcode::DPdyCoarse:
  590. info.uses_derivatives = true;
  591. break;
  592. case IR::Opcode::LoadStorageU8:
  593. case IR::Opcode::LoadStorageS8:
  594. case IR::Opcode::WriteStorageU8:
  595. case IR::Opcode::WriteStorageS8:
  596. info.used_storage_buffer_types |= IR::Type::U8;
  597. break;
  598. case IR::Opcode::LoadStorageU16:
  599. case IR::Opcode::LoadStorageS16:
  600. case IR::Opcode::WriteStorageU16:
  601. case IR::Opcode::WriteStorageS16:
  602. info.used_storage_buffer_types |= IR::Type::U16;
  603. break;
  604. case IR::Opcode::LoadStorage32:
  605. case IR::Opcode::WriteStorage32:
  606. case IR::Opcode::StorageAtomicIAdd32:
  607. case IR::Opcode::StorageAtomicUMin32:
  608. case IR::Opcode::StorageAtomicUMax32:
  609. case IR::Opcode::StorageAtomicAnd32:
  610. case IR::Opcode::StorageAtomicOr32:
  611. case IR::Opcode::StorageAtomicXor32:
  612. case IR::Opcode::StorageAtomicExchange32:
  613. info.used_storage_buffer_types |= IR::Type::U32;
  614. break;
  615. case IR::Opcode::LoadStorage64:
  616. case IR::Opcode::WriteStorage64:
  617. case IR::Opcode::StorageAtomicIAdd32x2:
  618. case IR::Opcode::StorageAtomicSMin32x2:
  619. case IR::Opcode::StorageAtomicUMin32x2:
  620. case IR::Opcode::StorageAtomicSMax32x2:
  621. case IR::Opcode::StorageAtomicUMax32x2:
  622. case IR::Opcode::StorageAtomicAnd32x2:
  623. case IR::Opcode::StorageAtomicOr32x2:
  624. case IR::Opcode::StorageAtomicXor32x2:
  625. case IR::Opcode::StorageAtomicExchange32x2:
  626. info.used_storage_buffer_types |= IR::Type::U32x2;
  627. break;
  628. case IR::Opcode::LoadStorage128:
  629. case IR::Opcode::WriteStorage128:
  630. info.used_storage_buffer_types |= IR::Type::U32x4;
  631. break;
  632. case IR::Opcode::SharedAtomicSMin32:
  633. info.uses_atomic_s32_min = true;
  634. break;
  635. case IR::Opcode::SharedAtomicSMax32:
  636. info.uses_atomic_s32_max = true;
  637. break;
  638. case IR::Opcode::SharedAtomicInc32:
  639. info.uses_shared_increment = true;
  640. break;
  641. case IR::Opcode::SharedAtomicDec32:
  642. info.uses_shared_decrement = true;
  643. break;
  644. case IR::Opcode::SharedAtomicExchange64:
  645. info.uses_int64_bit_atomics = true;
  646. break;
  647. case IR::Opcode::GlobalAtomicInc32:
  648. case IR::Opcode::StorageAtomicInc32:
  649. info.used_storage_buffer_types |= IR::Type::U32;
  650. info.uses_global_increment = true;
  651. break;
  652. case IR::Opcode::GlobalAtomicDec32:
  653. case IR::Opcode::StorageAtomicDec32:
  654. info.used_storage_buffer_types |= IR::Type::U32;
  655. info.uses_global_decrement = true;
  656. break;
  657. case IR::Opcode::GlobalAtomicAddF32:
  658. case IR::Opcode::StorageAtomicAddF32:
  659. info.used_storage_buffer_types |= IR::Type::U32;
  660. info.uses_atomic_f32_add = true;
  661. break;
  662. case IR::Opcode::GlobalAtomicAddF16x2:
  663. case IR::Opcode::StorageAtomicAddF16x2:
  664. info.used_storage_buffer_types |= IR::Type::U32;
  665. info.uses_atomic_f16x2_add = true;
  666. break;
  667. case IR::Opcode::GlobalAtomicAddF32x2:
  668. case IR::Opcode::StorageAtomicAddF32x2:
  669. info.used_storage_buffer_types |= IR::Type::U32;
  670. info.uses_atomic_f32x2_add = true;
  671. break;
  672. case IR::Opcode::GlobalAtomicMinF16x2:
  673. case IR::Opcode::StorageAtomicMinF16x2:
  674. info.used_storage_buffer_types |= IR::Type::U32;
  675. info.uses_atomic_f16x2_min = true;
  676. break;
  677. case IR::Opcode::GlobalAtomicMinF32x2:
  678. case IR::Opcode::StorageAtomicMinF32x2:
  679. info.used_storage_buffer_types |= IR::Type::U32;
  680. info.uses_atomic_f32x2_min = true;
  681. break;
  682. case IR::Opcode::GlobalAtomicMaxF16x2:
  683. case IR::Opcode::StorageAtomicMaxF16x2:
  684. info.used_storage_buffer_types |= IR::Type::U32;
  685. info.uses_atomic_f16x2_max = true;
  686. break;
  687. case IR::Opcode::GlobalAtomicMaxF32x2:
  688. case IR::Opcode::StorageAtomicMaxF32x2:
  689. info.used_storage_buffer_types |= IR::Type::U32;
  690. info.uses_atomic_f32x2_max = true;
  691. break;
  692. case IR::Opcode::StorageAtomicSMin32:
  693. info.used_storage_buffer_types |= IR::Type::U32;
  694. info.uses_atomic_s32_min = true;
  695. break;
  696. case IR::Opcode::StorageAtomicSMax32:
  697. info.used_storage_buffer_types |= IR::Type::U32;
  698. info.uses_atomic_s32_max = true;
  699. break;
  700. case IR::Opcode::GlobalAtomicIAdd64:
  701. case IR::Opcode::GlobalAtomicSMin64:
  702. case IR::Opcode::GlobalAtomicUMin64:
  703. case IR::Opcode::GlobalAtomicSMax64:
  704. case IR::Opcode::GlobalAtomicUMax64:
  705. case IR::Opcode::GlobalAtomicAnd64:
  706. case IR::Opcode::GlobalAtomicOr64:
  707. case IR::Opcode::GlobalAtomicXor64:
  708. case IR::Opcode::GlobalAtomicExchange64:
  709. case IR::Opcode::StorageAtomicIAdd64:
  710. case IR::Opcode::StorageAtomicSMin64:
  711. case IR::Opcode::StorageAtomicUMin64:
  712. case IR::Opcode::StorageAtomicSMax64:
  713. case IR::Opcode::StorageAtomicUMax64:
  714. case IR::Opcode::StorageAtomicAnd64:
  715. case IR::Opcode::StorageAtomicOr64:
  716. case IR::Opcode::StorageAtomicXor64:
  717. info.used_storage_buffer_types |= IR::Type::U64 | IR::Type::U32x2;
  718. info.uses_int64_bit_atomics = true;
  719. break;
  720. case IR::Opcode::BindlessImageAtomicIAdd32:
  721. case IR::Opcode::BindlessImageAtomicSMin32:
  722. case IR::Opcode::BindlessImageAtomicUMin32:
  723. case IR::Opcode::BindlessImageAtomicSMax32:
  724. case IR::Opcode::BindlessImageAtomicUMax32:
  725. case IR::Opcode::BindlessImageAtomicInc32:
  726. case IR::Opcode::BindlessImageAtomicDec32:
  727. case IR::Opcode::BindlessImageAtomicAnd32:
  728. case IR::Opcode::BindlessImageAtomicOr32:
  729. case IR::Opcode::BindlessImageAtomicXor32:
  730. case IR::Opcode::BindlessImageAtomicExchange32:
  731. case IR::Opcode::BoundImageAtomicIAdd32:
  732. case IR::Opcode::BoundImageAtomicSMin32:
  733. case IR::Opcode::BoundImageAtomicUMin32:
  734. case IR::Opcode::BoundImageAtomicSMax32:
  735. case IR::Opcode::BoundImageAtomicUMax32:
  736. case IR::Opcode::BoundImageAtomicInc32:
  737. case IR::Opcode::BoundImageAtomicDec32:
  738. case IR::Opcode::BoundImageAtomicAnd32:
  739. case IR::Opcode::BoundImageAtomicOr32:
  740. case IR::Opcode::BoundImageAtomicXor32:
  741. case IR::Opcode::BoundImageAtomicExchange32:
  742. case IR::Opcode::ImageAtomicIAdd32:
  743. case IR::Opcode::ImageAtomicSMin32:
  744. case IR::Opcode::ImageAtomicUMin32:
  745. case IR::Opcode::ImageAtomicSMax32:
  746. case IR::Opcode::ImageAtomicUMax32:
  747. case IR::Opcode::ImageAtomicInc32:
  748. case IR::Opcode::ImageAtomicDec32:
  749. case IR::Opcode::ImageAtomicAnd32:
  750. case IR::Opcode::ImageAtomicOr32:
  751. case IR::Opcode::ImageAtomicXor32:
  752. case IR::Opcode::ImageAtomicExchange32:
  753. info.uses_atomic_image_u32 = true;
  754. break;
  755. default:
  756. break;
  757. }
  758. }
  759. void VisitFpModifiers(Info& info, IR::Inst& inst) {
  760. switch (inst.GetOpcode()) {
  761. case IR::Opcode::FPAdd16:
  762. case IR::Opcode::FPFma16:
  763. case IR::Opcode::FPMul16:
  764. case IR::Opcode::FPRoundEven16:
  765. case IR::Opcode::FPFloor16:
  766. case IR::Opcode::FPCeil16:
  767. case IR::Opcode::FPTrunc16: {
  768. const auto control{inst.Flags<IR::FpControl>()};
  769. switch (control.fmz_mode) {
  770. case IR::FmzMode::DontCare:
  771. break;
  772. case IR::FmzMode::FTZ:
  773. case IR::FmzMode::FMZ:
  774. info.uses_fp16_denorms_flush = true;
  775. break;
  776. case IR::FmzMode::None:
  777. info.uses_fp16_denorms_preserve = true;
  778. break;
  779. }
  780. break;
  781. }
  782. case IR::Opcode::FPAdd32:
  783. case IR::Opcode::FPFma32:
  784. case IR::Opcode::FPMul32:
  785. case IR::Opcode::FPRoundEven32:
  786. case IR::Opcode::FPFloor32:
  787. case IR::Opcode::FPCeil32:
  788. case IR::Opcode::FPTrunc32:
  789. case IR::Opcode::FPOrdEqual32:
  790. case IR::Opcode::FPUnordEqual32:
  791. case IR::Opcode::FPOrdNotEqual32:
  792. case IR::Opcode::FPUnordNotEqual32:
  793. case IR::Opcode::FPOrdLessThan32:
  794. case IR::Opcode::FPUnordLessThan32:
  795. case IR::Opcode::FPOrdGreaterThan32:
  796. case IR::Opcode::FPUnordGreaterThan32:
  797. case IR::Opcode::FPOrdLessThanEqual32:
  798. case IR::Opcode::FPUnordLessThanEqual32:
  799. case IR::Opcode::FPOrdGreaterThanEqual32:
  800. case IR::Opcode::FPUnordGreaterThanEqual32:
  801. case IR::Opcode::ConvertF16F32:
  802. case IR::Opcode::ConvertF64F32: {
  803. const auto control{inst.Flags<IR::FpControl>()};
  804. switch (control.fmz_mode) {
  805. case IR::FmzMode::DontCare:
  806. break;
  807. case IR::FmzMode::FTZ:
  808. case IR::FmzMode::FMZ:
  809. info.uses_fp32_denorms_flush = true;
  810. break;
  811. case IR::FmzMode::None:
  812. info.uses_fp32_denorms_preserve = true;
  813. break;
  814. }
  815. break;
  816. }
  817. default:
  818. break;
  819. }
  820. }
  821. void VisitCbufs(Info& info, IR::Inst& inst) {
  822. switch (inst.GetOpcode()) {
  823. case IR::Opcode::GetCbufU8:
  824. case IR::Opcode::GetCbufS8:
  825. case IR::Opcode::GetCbufU16:
  826. case IR::Opcode::GetCbufS16:
  827. case IR::Opcode::GetCbufU32:
  828. case IR::Opcode::GetCbufF32:
  829. case IR::Opcode::GetCbufU32x2: {
  830. CheckCBufNVN(info, inst);
  831. break;
  832. }
  833. default:
  834. break;
  835. }
  836. }
  837. void Visit(Info& info, IR::Inst& inst) {
  838. VisitUsages(info, inst);
  839. VisitFpModifiers(info, inst);
  840. VisitCbufs(info, inst);
  841. }
  842. void GatherInfoFromHeader(Environment& env, Info& info) {
  843. Stage stage{env.ShaderStage()};
  844. if (stage == Stage::Compute) {
  845. return;
  846. }
  847. const auto& header{env.SPH()};
  848. if (stage == Stage::Fragment) {
  849. if (!info.loads_indexed_attributes) {
  850. return;
  851. }
  852. for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
  853. const size_t offset{static_cast<size_t>(IR::Attribute::Generic0X) + index * 4};
  854. const auto vector{header.ps.imap_generic_vector[index]};
  855. info.loads.mask[offset + 0] = vector.x != PixelImap::Unused;
  856. info.loads.mask[offset + 1] = vector.y != PixelImap::Unused;
  857. info.loads.mask[offset + 2] = vector.z != PixelImap::Unused;
  858. info.loads.mask[offset + 3] = vector.w != PixelImap::Unused;
  859. }
  860. return;
  861. }
  862. if (info.loads_indexed_attributes) {
  863. for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
  864. const IR::Attribute attribute{IR::Attribute::Generic0X + index * 4};
  865. const auto mask = header.vtg.InputGeneric(index);
  866. for (size_t i = 0; i < 4; ++i) {
  867. info.loads.Set(attribute + i, mask[i]);
  868. }
  869. }
  870. for (size_t index = 0; index < 8; ++index) {
  871. const u16 mask{header.vtg.clip_distances};
  872. info.loads.Set(IR::Attribute::ClipDistance0 + index, ((mask >> index) & 1) != 0);
  873. }
  874. info.loads.Set(IR::Attribute::PrimitiveId, header.vtg.imap_systemb.primitive_array_id != 0);
  875. info.loads.Set(IR::Attribute::Layer, header.vtg.imap_systemb.rt_array_index != 0);
  876. info.loads.Set(IR::Attribute::ViewportIndex, header.vtg.imap_systemb.viewport_index != 0);
  877. info.loads.Set(IR::Attribute::PointSize, header.vtg.imap_systemb.point_size != 0);
  878. info.loads.Set(IR::Attribute::PositionX, header.vtg.imap_systemb.position_x != 0);
  879. info.loads.Set(IR::Attribute::PositionY, header.vtg.imap_systemb.position_y != 0);
  880. info.loads.Set(IR::Attribute::PositionZ, header.vtg.imap_systemb.position_z != 0);
  881. info.loads.Set(IR::Attribute::PositionW, header.vtg.imap_systemb.position_w != 0);
  882. info.loads.Set(IR::Attribute::PointSpriteS, header.vtg.point_sprite_s != 0);
  883. info.loads.Set(IR::Attribute::PointSpriteT, header.vtg.point_sprite_t != 0);
  884. info.loads.Set(IR::Attribute::FogCoordinate, header.vtg.fog_coordinate != 0);
  885. info.loads.Set(IR::Attribute::TessellationEvaluationPointU,
  886. header.vtg.tessellation_eval_point_u != 0);
  887. info.loads.Set(IR::Attribute::TessellationEvaluationPointV,
  888. header.vtg.tessellation_eval_point_v != 0);
  889. info.loads.Set(IR::Attribute::InstanceId, header.vtg.instance_id != 0);
  890. info.loads.Set(IR::Attribute::VertexId, header.vtg.vertex_id != 0);
  891. // TODO: Legacy varyings
  892. }
  893. if (info.stores_indexed_attributes) {
  894. for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
  895. const IR::Attribute attribute{IR::Attribute::Generic0X + index * 4};
  896. const auto mask{header.vtg.OutputGeneric(index)};
  897. for (size_t i = 0; i < 4; ++i) {
  898. info.stores.Set(attribute + i, mask[i]);
  899. }
  900. }
  901. for (size_t index = 0; index < 8; ++index) {
  902. const u16 mask{header.vtg.omap_systemc.clip_distances};
  903. info.stores.Set(IR::Attribute::ClipDistance0 + index, ((mask >> index) & 1) != 0);
  904. }
  905. info.stores.Set(IR::Attribute::PrimitiveId,
  906. header.vtg.omap_systemb.primitive_array_id != 0);
  907. info.stores.Set(IR::Attribute::Layer, header.vtg.omap_systemb.rt_array_index != 0);
  908. info.stores.Set(IR::Attribute::ViewportIndex, header.vtg.omap_systemb.viewport_index != 0);
  909. info.stores.Set(IR::Attribute::PointSize, header.vtg.omap_systemb.point_size != 0);
  910. info.stores.Set(IR::Attribute::PositionX, header.vtg.omap_systemb.position_x != 0);
  911. info.stores.Set(IR::Attribute::PositionY, header.vtg.omap_systemb.position_y != 0);
  912. info.stores.Set(IR::Attribute::PositionZ, header.vtg.omap_systemb.position_z != 0);
  913. info.stores.Set(IR::Attribute::PositionW, header.vtg.omap_systemb.position_w != 0);
  914. info.stores.Set(IR::Attribute::PointSpriteS, header.vtg.omap_systemc.point_sprite_s != 0);
  915. info.stores.Set(IR::Attribute::PointSpriteT, header.vtg.omap_systemc.point_sprite_t != 0);
  916. info.stores.Set(IR::Attribute::FogCoordinate, header.vtg.omap_systemc.fog_coordinate != 0);
  917. info.stores.Set(IR::Attribute::TessellationEvaluationPointU,
  918. header.vtg.omap_systemc.tessellation_eval_point_u != 0);
  919. info.stores.Set(IR::Attribute::TessellationEvaluationPointV,
  920. header.vtg.omap_systemc.tessellation_eval_point_v != 0);
  921. info.stores.Set(IR::Attribute::InstanceId, header.vtg.omap_systemc.instance_id != 0);
  922. info.stores.Set(IR::Attribute::VertexId, header.vtg.omap_systemc.vertex_id != 0);
  923. // TODO: Legacy varyings
  924. }
  925. }
  926. } // Anonymous namespace
  927. void CollectShaderInfoPass(Environment& env, IR::Program& program) {
  928. Info& info{program.info};
  929. const u32 base{[&] {
  930. switch (program.stage) {
  931. case Stage::VertexA:
  932. case Stage::VertexB:
  933. return 0x110u;
  934. case Stage::TessellationControl:
  935. return 0x210u;
  936. case Stage::TessellationEval:
  937. return 0x310u;
  938. case Stage::Geometry:
  939. return 0x410u;
  940. case Stage::Fragment:
  941. return 0x510u;
  942. case Stage::Compute:
  943. return 0x310u;
  944. }
  945. throw InvalidArgument("Invalid stage {}", program.stage);
  946. }()};
  947. info.nvn_buffer_base = base;
  948. for (IR::Block* const block : program.post_order_blocks) {
  949. for (IR::Inst& inst : block->Instructions()) {
  950. Visit(info, inst);
  951. }
  952. }
  953. GatherInfoFromHeader(env, info);
  954. }
  955. } // namespace Shader::Optimization