node.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <array>
  6. #include <cstddef>
  7. #include <memory>
  8. #include <optional>
  9. #include <string>
  10. #include <tuple>
  11. #include <utility>
  12. #include <variant>
  13. #include <vector>
  14. #include "common/common_types.h"
  15. #include "video_core/engines/shader_bytecode.h"
  16. namespace VideoCommon::Shader {
  17. enum class OperationCode {
  18. Assign, /// (float& dest, float src) -> void
  19. Select, /// (MetaArithmetic, bool pred, float a, float b) -> float
  20. FAdd, /// (MetaArithmetic, float a, float b) -> float
  21. FMul, /// (MetaArithmetic, float a, float b) -> float
  22. FDiv, /// (MetaArithmetic, float a, float b) -> float
  23. FFma, /// (MetaArithmetic, float a, float b, float c) -> float
  24. FNegate, /// (MetaArithmetic, float a) -> float
  25. FAbsolute, /// (MetaArithmetic, float a) -> float
  26. FClamp, /// (MetaArithmetic, float value, float min, float max) -> float
  27. FCastHalf0, /// (MetaArithmetic, f16vec2 a) -> float
  28. FCastHalf1, /// (MetaArithmetic, f16vec2 a) -> float
  29. FMin, /// (MetaArithmetic, float a, float b) -> float
  30. FMax, /// (MetaArithmetic, float a, float b) -> float
  31. FCos, /// (MetaArithmetic, float a) -> float
  32. FSin, /// (MetaArithmetic, float a) -> float
  33. FExp2, /// (MetaArithmetic, float a) -> float
  34. FLog2, /// (MetaArithmetic, float a) -> float
  35. FInverseSqrt, /// (MetaArithmetic, float a) -> float
  36. FSqrt, /// (MetaArithmetic, float a) -> float
  37. FRoundEven, /// (MetaArithmetic, float a) -> float
  38. FFloor, /// (MetaArithmetic, float a) -> float
  39. FCeil, /// (MetaArithmetic, float a) -> float
  40. FTrunc, /// (MetaArithmetic, float a) -> float
  41. FCastInteger, /// (MetaArithmetic, int a) -> float
  42. FCastUInteger, /// (MetaArithmetic, uint a) -> float
  43. FSwizzleAdd, /// (float a, float b, uint mask) -> float
  44. IAdd, /// (MetaArithmetic, int a, int b) -> int
  45. IMul, /// (MetaArithmetic, int a, int b) -> int
  46. IDiv, /// (MetaArithmetic, int a, int b) -> int
  47. INegate, /// (MetaArithmetic, int a) -> int
  48. IAbsolute, /// (MetaArithmetic, int a) -> int
  49. IMin, /// (MetaArithmetic, int a, int b) -> int
  50. IMax, /// (MetaArithmetic, int a, int b) -> int
  51. ICastFloat, /// (MetaArithmetic, float a) -> int
  52. ICastUnsigned, /// (MetaArithmetic, uint a) -> int
  53. ILogicalShiftLeft, /// (MetaArithmetic, int a, uint b) -> int
  54. ILogicalShiftRight, /// (MetaArithmetic, int a, uint b) -> int
  55. IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int
  56. IBitwiseAnd, /// (MetaArithmetic, int a, int b) -> int
  57. IBitwiseOr, /// (MetaArithmetic, int a, int b) -> int
  58. IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int
  59. IBitwiseNot, /// (MetaArithmetic, int a) -> int
  60. IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
  61. IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int
  62. IBitCount, /// (MetaArithmetic, int) -> int
  63. IBitMSB, /// (MetaArithmetic, int) -> int
  64. UAdd, /// (MetaArithmetic, uint a, uint b) -> uint
  65. UMul, /// (MetaArithmetic, uint a, uint b) -> uint
  66. UDiv, /// (MetaArithmetic, uint a, uint b) -> uint
  67. UMin, /// (MetaArithmetic, uint a, uint b) -> uint
  68. UMax, /// (MetaArithmetic, uint a, uint b) -> uint
  69. UCastFloat, /// (MetaArithmetic, float a) -> uint
  70. UCastSigned, /// (MetaArithmetic, int a) -> uint
  71. ULogicalShiftLeft, /// (MetaArithmetic, uint a, uint b) -> uint
  72. ULogicalShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
  73. UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
  74. UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint
  75. UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint
  76. UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint
  77. UBitwiseNot, /// (MetaArithmetic, uint a) -> uint
  78. UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
  79. UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
  80. UBitCount, /// (MetaArithmetic, uint) -> uint
  81. UBitMSB, /// (MetaArithmetic, uint) -> uint
  82. HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
  83. HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
  84. HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
  85. HAbsolute, /// (f16vec2 a) -> f16vec2
  86. HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2
  87. HClamp, /// (f16vec2 src, float min, float max) -> f16vec2
  88. HCastFloat, /// (MetaArithmetic, float a) -> f16vec2
  89. HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2
  90. HMergeF32, /// (f16vec2 src) -> float
  91. HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
  92. HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
  93. HPack2, /// (float a, float b) -> f16vec2
  94. LogicalAssign, /// (bool& dst, bool src) -> void
  95. LogicalAnd, /// (bool a, bool b) -> bool
  96. LogicalOr, /// (bool a, bool b) -> bool
  97. LogicalXor, /// (bool a, bool b) -> bool
  98. LogicalNegate, /// (bool a) -> bool
  99. LogicalPick2, /// (bool2 pair, uint index) -> bool
  100. LogicalAnd2, /// (bool2 a) -> bool
  101. LogicalFOrdLessThan, /// (float a, float b) -> bool
  102. LogicalFOrdEqual, /// (float a, float b) -> bool
  103. LogicalFOrdLessEqual, /// (float a, float b) -> bool
  104. LogicalFOrdGreaterThan, /// (float a, float b) -> bool
  105. LogicalFOrdNotEqual, /// (float a, float b) -> bool
  106. LogicalFOrdGreaterEqual, /// (float a, float b) -> bool
  107. LogicalFOrdered, /// (float a, float b) -> bool
  108. LogicalFUnordered, /// (float a, float b) -> bool
  109. LogicalFUnordLessThan, /// (float a, float b) -> bool
  110. LogicalFUnordEqual, /// (float a, float b) -> bool
  111. LogicalFUnordLessEqual, /// (float a, float b) -> bool
  112. LogicalFUnordGreaterThan, /// (float a, float b) -> bool
  113. LogicalFUnordNotEqual, /// (float a, float b) -> bool
  114. LogicalFUnordGreaterEqual, /// (float a, float b) -> bool
  115. LogicalILessThan, /// (int a, int b) -> bool
  116. LogicalIEqual, /// (int a, int b) -> bool
  117. LogicalILessEqual, /// (int a, int b) -> bool
  118. LogicalIGreaterThan, /// (int a, int b) -> bool
  119. LogicalINotEqual, /// (int a, int b) -> bool
  120. LogicalIGreaterEqual, /// (int a, int b) -> bool
  121. LogicalULessThan, /// (uint a, uint b) -> bool
  122. LogicalUEqual, /// (uint a, uint b) -> bool
  123. LogicalULessEqual, /// (uint a, uint b) -> bool
  124. LogicalUGreaterThan, /// (uint a, uint b) -> bool
  125. LogicalUNotEqual, /// (uint a, uint b) -> bool
  126. LogicalUGreaterEqual, /// (uint a, uint b) -> bool
  127. LogicalAddCarry, /// (uint a, uint b) -> bool
  128. Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  129. Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  130. Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  131. Logical2HGreaterThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  132. Logical2HNotEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  133. Logical2HGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  134. Logical2HLessThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  135. Logical2HEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  136. Logical2HLessEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  137. Logical2HGreaterThanWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  138. Logical2HNotEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  139. Logical2HGreaterEqualWithNan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
  140. Texture, /// (MetaTexture, float[N] coords) -> float4
  141. TextureLod, /// (MetaTexture, float[N] coords) -> float4
  142. TextureGather, /// (MetaTexture, float[N] coords) -> float4
  143. TextureQueryDimensions, /// (MetaTexture, float a) -> float4
  144. TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4
  145. TexelFetch, /// (MetaTexture, int[N], int) -> float4
  146. TextureGradient, /// (MetaTexture, float[N] coords, float[N*2] derivates) -> float4
  147. ImageLoad, /// (MetaImage, int[N] coords) -> void
  148. ImageStore, /// (MetaImage, int[N] coords) -> void
  149. AtomicImageAdd, /// (MetaImage, int[N] coords) -> void
  150. AtomicImageAnd, /// (MetaImage, int[N] coords) -> void
  151. AtomicImageOr, /// (MetaImage, int[N] coords) -> void
  152. AtomicImageXor, /// (MetaImage, int[N] coords) -> void
  153. AtomicImageExchange, /// (MetaImage, int[N] coords) -> void
  154. AtomicUExchange, /// (memory, uint) -> uint
  155. AtomicUAdd, /// (memory, uint) -> uint
  156. AtomicUMin, /// (memory, uint) -> uint
  157. AtomicUMax, /// (memory, uint) -> uint
  158. AtomicUAnd, /// (memory, uint) -> uint
  159. AtomicUOr, /// (memory, uint) -> uint
  160. AtomicUXor, /// (memory, uint) -> uint
  161. AtomicIExchange, /// (memory, int) -> int
  162. AtomicIAdd, /// (memory, int) -> int
  163. AtomicIMin, /// (memory, int) -> int
  164. AtomicIMax, /// (memory, int) -> int
  165. AtomicIAnd, /// (memory, int) -> int
  166. AtomicIOr, /// (memory, int) -> int
  167. AtomicIXor, /// (memory, int) -> int
  168. ReduceUAdd, /// (memory, uint) -> void
  169. ReduceUMin, /// (memory, uint) -> void
  170. ReduceUMax, /// (memory, uint) -> void
  171. ReduceUAnd, /// (memory, uint) -> void
  172. ReduceUOr, /// (memory, uint) -> void
  173. ReduceUXor, /// (memory, uint) -> void
  174. ReduceIAdd, /// (memory, int) -> void
  175. ReduceIMin, /// (memory, int) -> void
  176. ReduceIMax, /// (memory, int) -> void
  177. ReduceIAnd, /// (memory, int) -> void
  178. ReduceIOr, /// (memory, int) -> void
  179. ReduceIXor, /// (memory, int) -> void
  180. Branch, /// (uint branch_target) -> void
  181. BranchIndirect, /// (uint branch_target) -> void
  182. PushFlowStack, /// (uint branch_target) -> void
  183. PopFlowStack, /// () -> void
  184. Exit, /// () -> void
  185. Discard, /// () -> void
  186. EmitVertex, /// () -> void
  187. EndPrimitive, /// () -> void
  188. InvocationId, /// () -> int
  189. YNegate, /// () -> float
  190. LocalInvocationIdX, /// () -> uint
  191. LocalInvocationIdY, /// () -> uint
  192. LocalInvocationIdZ, /// () -> uint
  193. WorkGroupIdX, /// () -> uint
  194. WorkGroupIdY, /// () -> uint
  195. WorkGroupIdZ, /// () -> uint
  196. BallotThread, /// (bool) -> uint
  197. VoteAll, /// (bool) -> bool
  198. VoteAny, /// (bool) -> bool
  199. VoteEqual, /// (bool) -> bool
  200. ThreadId, /// () -> uint
  201. ThreadEqMask, /// () -> uint
  202. ThreadGeMask, /// () -> uint
  203. ThreadGtMask, /// () -> uint
  204. ThreadLeMask, /// () -> uint
  205. ThreadLtMask, /// () -> uint
  206. ShuffleIndexed, /// (uint value, uint index) -> uint
  207. Barrier, /// () -> void
  208. MemoryBarrierGroup, /// () -> void
  209. MemoryBarrierGlobal, /// () -> void
  210. Amount,
  211. };
  212. enum class InternalFlag {
  213. Zero = 0,
  214. Sign = 1,
  215. Carry = 2,
  216. Overflow = 3,
  217. Amount = 4,
  218. };
  219. enum class MetaStackClass {
  220. Ssy,
  221. Pbk,
  222. };
  223. class OperationNode;
  224. class ConditionalNode;
  225. class GprNode;
  226. class CustomVarNode;
  227. class ImmediateNode;
  228. class InternalFlagNode;
  229. class PredicateNode;
  230. class AbufNode;
  231. class CbufNode;
  232. class LmemNode;
  233. class PatchNode;
  234. class SmemNode;
  235. class GmemNode;
  236. class CommentNode;
  237. using NodeData = std::variant<OperationNode, ConditionalNode, GprNode, CustomVarNode, ImmediateNode,
  238. InternalFlagNode, PredicateNode, AbufNode, PatchNode, CbufNode,
  239. LmemNode, SmemNode, GmemNode, CommentNode>;
  240. using Node = std::shared_ptr<NodeData>;
  241. using Node4 = std::array<Node, 4>;
  242. using NodeBlock = std::vector<Node>;
  243. struct ArraySamplerNode;
  244. struct BindlessSamplerNode;
  245. struct SeparateSamplerNode;
  246. using TrackSamplerData = std::variant<BindlessSamplerNode, SeparateSamplerNode, ArraySamplerNode>;
  247. using TrackSampler = std::shared_ptr<TrackSamplerData>;
  248. struct Sampler {
  249. /// Bound samplers constructor
  250. constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
  251. bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
  252. : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow},
  253. is_buffer{is_buffer}, is_indexed{is_indexed} {}
  254. /// Separate sampler constructor
  255. constexpr explicit Sampler(u32 index, std::pair<u32, u32> offsets, std::pair<u32, u32> buffers,
  256. Tegra::Shader::TextureType type, bool is_array, bool is_shadow,
  257. bool is_buffer)
  258. : index{index}, offset{offsets.first}, secondary_offset{offsets.second},
  259. buffer{buffers.first}, secondary_buffer{buffers.second}, type{type}, is_array{is_array},
  260. is_shadow{is_shadow}, is_buffer{is_buffer}, is_separated{true} {}
  261. /// Bindless samplers constructor
  262. constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
  263. bool is_array, bool is_shadow, bool is_buffer, bool is_indexed)
  264. : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
  265. is_shadow{is_shadow}, is_buffer{is_buffer}, is_bindless{true}, is_indexed{is_indexed} {}
  266. u32 index = 0; ///< Emulated index given for the this sampler.
  267. u32 offset = 0; ///< Offset in the const buffer from where the sampler is being read.
  268. u32 secondary_offset = 0; ///< Secondary offset in the const buffer.
  269. u32 buffer = 0; ///< Buffer where the bindless sampler is read.
  270. u32 secondary_buffer = 0; ///< Secondary buffer where the bindless sampler is read.
  271. u32 size = 1; ///< Size of the sampler.
  272. Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
  273. bool is_array = false; ///< Whether the texture is being sampled as an array texture or not.
  274. bool is_shadow = false; ///< Whether the texture is being sampled as a depth texture or not.
  275. bool is_buffer = false; ///< Whether the texture is a texture buffer without sampler.
  276. bool is_bindless = false; ///< Whether this sampler belongs to a bindless texture or not.
  277. bool is_indexed = false; ///< Whether this sampler is an indexed array of textures.
  278. bool is_separated = false; ///< Whether the image and sampler is separated or not.
  279. };
  280. /// Represents a tracked bindless sampler into a direct const buffer
  281. struct ArraySamplerNode {
  282. u32 index;
  283. u32 base_offset;
  284. u32 bindless_var;
  285. };
  286. /// Represents a tracked separate sampler image pair that was folded statically
  287. struct SeparateSamplerNode {
  288. std::pair<u32, u32> indices;
  289. std::pair<u32, u32> offsets;
  290. };
  291. /// Represents a tracked bindless sampler into a direct const buffer
  292. struct BindlessSamplerNode {
  293. u32 index;
  294. u32 offset;
  295. };
  296. struct Image {
  297. public:
  298. /// Bound images constructor
  299. constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type)
  300. : index{index}, offset{offset}, type{type} {}
  301. /// Bindless samplers constructor
  302. constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type)
  303. : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {}
  304. void MarkWrite() {
  305. is_written = true;
  306. }
  307. void MarkRead() {
  308. is_read = true;
  309. }
  310. void MarkAtomic() {
  311. MarkWrite();
  312. MarkRead();
  313. is_atomic = true;
  314. }
  315. u32 index = 0;
  316. u32 offset = 0;
  317. u32 buffer = 0;
  318. Tegra::Shader::ImageType type{};
  319. bool is_bindless = false;
  320. bool is_written = false;
  321. bool is_read = false;
  322. bool is_atomic = false;
  323. };
  324. struct GlobalMemoryBase {
  325. u32 cbuf_index = 0;
  326. u32 cbuf_offset = 0;
  327. bool operator<(const GlobalMemoryBase& rhs) const {
  328. return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset);
  329. }
  330. };
  331. /// Parameters describing an arithmetic operation
  332. struct MetaArithmetic {
  333. bool precise{}; ///< Whether the operation can be constraint or not
  334. };
  335. /// Parameters describing a texture sampler
  336. struct MetaTexture {
  337. Sampler sampler;
  338. Node array;
  339. Node depth_compare;
  340. std::vector<Node> aoffi;
  341. std::vector<Node> ptp;
  342. std::vector<Node> derivates;
  343. Node bias;
  344. Node lod;
  345. Node component;
  346. u32 element{};
  347. Node index;
  348. };
  349. struct MetaImage {
  350. const Image& image;
  351. std::vector<Node> values;
  352. u32 element{};
  353. };
  354. /// Parameters that modify an operation but are not part of any particular operand
  355. using Meta =
  356. std::variant<MetaArithmetic, MetaTexture, MetaImage, MetaStackClass, Tegra::Shader::HalfType>;
  357. class AmendNode {
  358. public:
  359. std::optional<std::size_t> GetAmendIndex() const {
  360. if (amend_index == amend_null_index) {
  361. return std::nullopt;
  362. }
  363. return {amend_index};
  364. }
  365. void SetAmendIndex(std::size_t index) {
  366. amend_index = index;
  367. }
  368. void ClearAmend() {
  369. amend_index = amend_null_index;
  370. }
  371. private:
  372. static constexpr std::size_t amend_null_index = 0xFFFFFFFFFFFFFFFFULL;
  373. std::size_t amend_index{amend_null_index};
  374. };
  375. /// Holds any kind of operation that can be done in the IR
  376. class OperationNode final : public AmendNode {
  377. public:
  378. explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
  379. explicit OperationNode(OperationCode code, Meta meta)
  380. : OperationNode(code, std::move(meta), std::vector<Node>{}) {}
  381. explicit OperationNode(OperationCode code, std::vector<Node> operands)
  382. : OperationNode(code, Meta{}, std::move(operands)) {}
  383. explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands)
  384. : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {}
  385. template <typename... Args>
  386. explicit OperationNode(OperationCode code, Meta meta, Args&&... operands)
  387. : code{code}, meta{std::move(meta)}, operands{operands...} {}
  388. OperationCode GetCode() const {
  389. return code;
  390. }
  391. const Meta& GetMeta() const {
  392. return meta;
  393. }
  394. std::size_t GetOperandsCount() const {
  395. return operands.size();
  396. }
  397. const Node& operator[](std::size_t operand_index) const {
  398. return operands.at(operand_index);
  399. }
  400. private:
  401. OperationCode code{};
  402. Meta meta{};
  403. std::vector<Node> operands;
  404. };
  405. /// Encloses inside any kind of node that returns a boolean conditionally-executed code
  406. class ConditionalNode final : public AmendNode {
  407. public:
  408. explicit ConditionalNode(Node condition, std::vector<Node>&& code)
  409. : condition{std::move(condition)}, code{std::move(code)} {}
  410. const Node& GetCondition() const {
  411. return condition;
  412. }
  413. const std::vector<Node>& GetCode() const {
  414. return code;
  415. }
  416. private:
  417. Node condition; ///< Condition to be satisfied
  418. std::vector<Node> code; ///< Code to execute
  419. };
  420. /// A general purpose register
  421. class GprNode final {
  422. public:
  423. explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {}
  424. u32 GetIndex() const {
  425. return static_cast<u32>(index);
  426. }
  427. private:
  428. Tegra::Shader::Register index{};
  429. };
  430. /// A custom variable
  431. class CustomVarNode final {
  432. public:
  433. explicit constexpr CustomVarNode(u32 index) : index{index} {}
  434. constexpr u32 GetIndex() const {
  435. return index;
  436. }
  437. private:
  438. u32 index{};
  439. };
  440. /// A 32-bits value that represents an immediate value
  441. class ImmediateNode final {
  442. public:
  443. explicit constexpr ImmediateNode(u32 value) : value{value} {}
  444. u32 GetValue() const {
  445. return value;
  446. }
  447. private:
  448. u32 value{};
  449. };
  450. /// One of Maxwell's internal flags
  451. class InternalFlagNode final {
  452. public:
  453. explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {}
  454. InternalFlag GetFlag() const {
  455. return flag;
  456. }
  457. private:
  458. InternalFlag flag{};
  459. };
  460. /// A predicate register, it can be negated without additional nodes
  461. class PredicateNode final {
  462. public:
  463. explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated)
  464. : index{index}, negated{negated} {}
  465. Tegra::Shader::Pred GetIndex() const {
  466. return index;
  467. }
  468. bool IsNegated() const {
  469. return negated;
  470. }
  471. private:
  472. Tegra::Shader::Pred index{};
  473. bool negated{};
  474. };
  475. /// Attribute buffer memory (known as attributes or varyings in GLSL terms)
  476. class AbufNode final {
  477. public:
  478. // Initialize for standard attributes (index is explicit).
  479. explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {})
  480. : buffer{std::move(buffer)}, index{index}, element{element} {}
  481. // Initialize for physical attributes (index is a variable value).
  482. explicit AbufNode(Node physical_address, Node buffer = {})
  483. : physical_address{std::move(physical_address)}, buffer{std::move(buffer)} {}
  484. Tegra::Shader::Attribute::Index GetIndex() const {
  485. return index;
  486. }
  487. u32 GetElement() const {
  488. return element;
  489. }
  490. const Node& GetBuffer() const {
  491. return buffer;
  492. }
  493. bool IsPhysicalBuffer() const {
  494. return static_cast<bool>(physical_address);
  495. }
  496. const Node& GetPhysicalAddress() const {
  497. return physical_address;
  498. }
  499. private:
  500. Node physical_address;
  501. Node buffer;
  502. Tegra::Shader::Attribute::Index index{};
  503. u32 element{};
  504. };
  505. /// Patch memory (used to communicate tessellation stages).
  506. class PatchNode final {
  507. public:
  508. explicit PatchNode(u32 offset) : offset{offset} {}
  509. u32 GetOffset() const {
  510. return offset;
  511. }
  512. private:
  513. u32 offset{};
  514. };
  515. /// Constant buffer node, usually mapped to uniform buffers in GLSL
  516. class CbufNode final {
  517. public:
  518. explicit CbufNode(u32 index, Node offset) : index{index}, offset{std::move(offset)} {}
  519. u32 GetIndex() const {
  520. return index;
  521. }
  522. const Node& GetOffset() const {
  523. return offset;
  524. }
  525. private:
  526. u32 index{};
  527. Node offset;
  528. };
  529. /// Local memory node
  530. class LmemNode final {
  531. public:
  532. explicit LmemNode(Node address) : address{std::move(address)} {}
  533. const Node& GetAddress() const {
  534. return address;
  535. }
  536. private:
  537. Node address;
  538. };
  539. /// Shared memory node
  540. class SmemNode final {
  541. public:
  542. explicit SmemNode(Node address) : address{std::move(address)} {}
  543. const Node& GetAddress() const {
  544. return address;
  545. }
  546. private:
  547. Node address;
  548. };
  549. /// Global memory node
  550. class GmemNode final {
  551. public:
  552. explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor)
  553. : real_address{std::move(real_address)}, base_address{std::move(base_address)},
  554. descriptor{descriptor} {}
  555. const Node& GetRealAddress() const {
  556. return real_address;
  557. }
  558. const Node& GetBaseAddress() const {
  559. return base_address;
  560. }
  561. const GlobalMemoryBase& GetDescriptor() const {
  562. return descriptor;
  563. }
  564. private:
  565. Node real_address;
  566. Node base_address;
  567. GlobalMemoryBase descriptor;
  568. };
  569. /// Commentary, can be dropped
  570. class CommentNode final {
  571. public:
  572. explicit CommentNode(std::string text) : text{std::move(text)} {}
  573. const std::string& GetText() const {
  574. return text;
  575. }
  576. private:
  577. std::string text;
  578. };
  579. } // namespace VideoCommon::Shader