shader_bytecode.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <cstring>
  6. #include <map>
  7. #include <string>
  8. #include "common/bit_field.h"
  9. namespace Tegra {
  10. namespace Shader {
  11. struct Register {
  12. // Register 255 is special cased to always be 0
  13. static constexpr size_t ZeroIndex = 255;
  14. constexpr Register() = default;
  15. constexpr Register(u64 value) : value(value) {}
  16. constexpr operator u64() const {
  17. return value;
  18. }
  19. template <typename T>
  20. constexpr u64 operator-(const T& oth) const {
  21. return value - oth;
  22. }
  23. template <typename T>
  24. constexpr u64 operator&(const T& oth) const {
  25. return value & oth;
  26. }
  27. constexpr u64 operator&(const Register& oth) const {
  28. return value & oth.value;
  29. }
  30. constexpr u64 operator~() const {
  31. return ~value;
  32. }
  33. private:
  34. u64 value{};
  35. };
  36. union Attribute {
  37. Attribute() = default;
  38. constexpr explicit Attribute(u64 value) : value(value) {}
  39. enum class Index : u64 {
  40. Position = 7,
  41. Attribute_0 = 8,
  42. };
  43. union {
  44. BitField<22, 2, u64> element;
  45. BitField<24, 6, Index> index;
  46. BitField<47, 3, u64> size;
  47. } fmt20;
  48. union {
  49. BitField<30, 2, u64> element;
  50. BitField<32, 6, Index> index;
  51. } fmt28;
  52. BitField<39, 8, u64> reg;
  53. u64 value{};
  54. };
  55. union Sampler {
  56. Sampler() = default;
  57. constexpr explicit Sampler(u64 value) : value(value) {}
  58. enum class Index : u64 {
  59. Sampler_0 = 8,
  60. };
  61. BitField<36, 13, Index> index;
  62. u64 value{};
  63. };
  64. union Uniform {
  65. BitField<20, 14, u64> offset;
  66. BitField<34, 5, u64> index;
  67. };
  68. union OpCode {
  69. enum class Id : u64 {
  70. TEXS = 0x6C,
  71. IPA = 0xE0,
  72. FMUL32_IMM = 0x1E,
  73. FFMA_IMM = 0x65,
  74. FFMA_CR = 0x93,
  75. FFMA_RC = 0xA3,
  76. FFMA_RR = 0xB3,
  77. FADD_C = 0x98B,
  78. FMUL_C = 0x98D,
  79. MUFU = 0xA10,
  80. FADD_R = 0xB8B,
  81. FMUL_R = 0xB8D,
  82. LD_A = 0x1DFB,
  83. ST_A = 0x1DFE,
  84. FSETP_R = 0x5BB,
  85. FSETP_C = 0x4BB,
  86. FSETP_IMM = 0x36B,
  87. FSETP_NEG_IMM = 0x37B,
  88. EXIT = 0xE30,
  89. KIL = 0xE33,
  90. FMUL_IMM = 0x70D,
  91. FMUL_IMM_x = 0x72D,
  92. FADD_IMM = 0x70B,
  93. FADD_IMM_x = 0x72B,
  94. };
  95. enum class Type {
  96. Trivial,
  97. Arithmetic,
  98. Ffma,
  99. Flow,
  100. Memory,
  101. FloatPredicate,
  102. Unknown,
  103. };
  104. struct Info {
  105. Type type;
  106. std::string name;
  107. };
  108. OpCode() = default;
  109. constexpr OpCode(Id value) : value(static_cast<u64>(value)) {}
  110. constexpr OpCode(u64 value) : value{value} {}
  111. constexpr Id EffectiveOpCode() const {
  112. switch (op1) {
  113. case Id::TEXS:
  114. return op1;
  115. }
  116. switch (op2) {
  117. case Id::IPA:
  118. case Id::FMUL32_IMM:
  119. return op2;
  120. }
  121. switch (op3) {
  122. case Id::FFMA_IMM:
  123. case Id::FFMA_CR:
  124. case Id::FFMA_RC:
  125. case Id::FFMA_RR:
  126. return op3;
  127. }
  128. switch (op4) {
  129. case Id::EXIT:
  130. case Id::FSETP_R:
  131. case Id::FSETP_C:
  132. case Id::KIL:
  133. return op4;
  134. case Id::FSETP_IMM:
  135. case Id::FSETP_NEG_IMM:
  136. return Id::FSETP_IMM;
  137. }
  138. switch (op5) {
  139. case Id::MUFU:
  140. case Id::LD_A:
  141. case Id::ST_A:
  142. case Id::FADD_R:
  143. case Id::FADD_C:
  144. case Id::FMUL_R:
  145. case Id::FMUL_C:
  146. return op5;
  147. case Id::FMUL_IMM:
  148. case Id::FMUL_IMM_x:
  149. return Id::FMUL_IMM;
  150. case Id::FADD_IMM:
  151. case Id::FADD_IMM_x:
  152. return Id::FADD_IMM;
  153. }
  154. return static_cast<Id>(value);
  155. }
  156. static const Info& GetInfo(const OpCode& opcode) {
  157. static const std::map<Id, Info> info_table{BuildInfoTable()};
  158. const auto& search{info_table.find(opcode.EffectiveOpCode())};
  159. if (search != info_table.end()) {
  160. return search->second;
  161. }
  162. static const Info unknown{Type::Unknown, "UNK"};
  163. return unknown;
  164. }
  165. constexpr operator Id() const {
  166. return static_cast<Id>(value);
  167. }
  168. constexpr OpCode operator<<(size_t bits) const {
  169. return value << bits;
  170. }
  171. constexpr OpCode operator>>(size_t bits) const {
  172. return value >> bits;
  173. }
  174. template <typename T>
  175. constexpr u64 operator-(const T& oth) const {
  176. return value - oth;
  177. }
  178. constexpr u64 operator&(const OpCode& oth) const {
  179. return value & oth.value;
  180. }
  181. constexpr u64 operator~() const {
  182. return ~value;
  183. }
  184. static std::map<Id, Info> BuildInfoTable() {
  185. std::map<Id, Info> info_table;
  186. info_table[Id::TEXS] = {Type::Memory, "texs"};
  187. info_table[Id::LD_A] = {Type::Memory, "ld_a"};
  188. info_table[Id::ST_A] = {Type::Memory, "st_a"};
  189. info_table[Id::MUFU] = {Type::Arithmetic, "mufu"};
  190. info_table[Id::FFMA_IMM] = {Type::Ffma, "ffma_imm"};
  191. info_table[Id::FFMA_CR] = {Type::Ffma, "ffma_cr"};
  192. info_table[Id::FFMA_RC] = {Type::Ffma, "ffma_rc"};
  193. info_table[Id::FFMA_RR] = {Type::Ffma, "ffma_rr"};
  194. info_table[Id::FADD_R] = {Type::Arithmetic, "fadd_r"};
  195. info_table[Id::FADD_C] = {Type::Arithmetic, "fadd_c"};
  196. info_table[Id::FADD_IMM] = {Type::Arithmetic, "fadd_imm"};
  197. info_table[Id::FMUL_R] = {Type::Arithmetic, "fmul_r"};
  198. info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"};
  199. info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"};
  200. info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"};
  201. info_table[Id::FSETP_C] = {Type::FloatPredicate, "fsetp_c"};
  202. info_table[Id::FSETP_R] = {Type::FloatPredicate, "fsetp_r"};
  203. info_table[Id::FSETP_IMM] = {Type::FloatPredicate, "fsetp_imm"};
  204. info_table[Id::EXIT] = {Type::Trivial, "exit"};
  205. info_table[Id::IPA] = {Type::Trivial, "ipa"};
  206. info_table[Id::KIL] = {Type::Flow, "kil"};
  207. return info_table;
  208. }
  209. BitField<57, 7, Id> op1;
  210. BitField<56, 8, Id> op2;
  211. BitField<55, 9, Id> op3;
  212. BitField<52, 12, Id> op4;
  213. BitField<51, 13, Id> op5;
  214. u64 value{};
  215. };
  216. static_assert(sizeof(OpCode) == 0x8, "Incorrect structure size");
  217. } // namespace Shader
  218. } // namespace Tegra
  219. namespace std {
  220. // TODO(bunne): The below is forbidden by the C++ standard, but works fine. See #330.
  221. template <>
  222. struct make_unsigned<Tegra::Shader::Attribute> {
  223. using type = Tegra::Shader::Attribute;
  224. };
  225. template <>
  226. struct make_unsigned<Tegra::Shader::Register> {
  227. using type = Tegra::Shader::Register;
  228. };
  229. template <>
  230. struct make_unsigned<Tegra::Shader::OpCode> {
  231. using type = Tegra::Shader::OpCode;
  232. };
  233. } // namespace std
  234. namespace Tegra {
  235. namespace Shader {
  236. enum class Pred : u64 {
  237. UnusedIndex = 0x7,
  238. NeverExecute = 0xF,
  239. };
  240. enum class PredCondition : u64 {
  241. LessThan = 1,
  242. Equal = 2,
  243. LessEqual = 3,
  244. GreaterThan = 4,
  245. NotEqual = 5,
  246. GreaterEqual = 6,
  247. // TODO(Subv): Other condition types
  248. };
  249. enum class PredOperation : u64 {
  250. And = 0,
  251. Or = 1,
  252. Xor = 2,
  253. };
  254. enum class SubOp : u64 {
  255. Cos = 0x0,
  256. Sin = 0x1,
  257. Ex2 = 0x2,
  258. Lg2 = 0x3,
  259. Rcp = 0x4,
  260. Rsq = 0x5,
  261. Min = 0x8,
  262. };
  263. union Instruction {
  264. Instruction& operator=(const Instruction& instr) {
  265. hex = instr.hex;
  266. return *this;
  267. }
  268. OpCode opcode;
  269. BitField<0, 8, Register> gpr0;
  270. BitField<8, 8, Register> gpr8;
  271. union {
  272. BitField<16, 4, Pred> full_pred;
  273. BitField<16, 3, u64> pred_index;
  274. } pred;
  275. BitField<19, 1, u64> negate_pred;
  276. BitField<20, 8, Register> gpr20;
  277. BitField<20, 7, SubOp> sub_op;
  278. BitField<28, 8, Register> gpr28;
  279. BitField<39, 8, Register> gpr39;
  280. union {
  281. BitField<20, 19, u64> imm20_19;
  282. BitField<20, 32, u64> imm20_32;
  283. BitField<45, 1, u64> negate_b;
  284. BitField<46, 1, u64> abs_a;
  285. BitField<48, 1, u64> negate_a;
  286. BitField<49, 1, u64> abs_b;
  287. BitField<50, 1, u64> abs_d;
  288. BitField<56, 1, u64> negate_imm;
  289. float GetImm20_19() const {
  290. float result{};
  291. u32 imm{static_cast<u32>(imm20_19)};
  292. imm <<= 12;
  293. imm |= negate_imm ? 0x80000000 : 0;
  294. std::memcpy(&result, &imm, sizeof(imm));
  295. return result;
  296. }
  297. float GetImm20_32() const {
  298. float result{};
  299. u32 imm{static_cast<u32>(imm20_32)};
  300. std::memcpy(&result, &imm, sizeof(imm));
  301. return result;
  302. }
  303. } alu;
  304. union {
  305. BitField<48, 1, u64> negate_b;
  306. BitField<49, 1, u64> negate_c;
  307. } ffma;
  308. union {
  309. BitField<0, 3, u64> pred0;
  310. BitField<3, 3, u64> pred3;
  311. BitField<7, 1, u64> abs_a;
  312. BitField<39, 3, u64> pred39;
  313. BitField<42, 1, u64> neg_pred;
  314. BitField<43, 1, u64> neg_a;
  315. BitField<44, 1, u64> abs_b;
  316. BitField<45, 2, PredOperation> op;
  317. BitField<47, 1, u64> ftz;
  318. BitField<48, 4, PredCondition> cond;
  319. BitField<56, 1, u64> neg_b;
  320. } fsetp;
  321. BitField<61, 1, u64> is_b_imm;
  322. BitField<60, 1, u64> is_b_gpr;
  323. BitField<59, 1, u64> is_c_gpr;
  324. Attribute attribute;
  325. Uniform uniform;
  326. Sampler sampler;
  327. u64 hex;
  328. };
  329. static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size");
  330. static_assert(std::is_standard_layout<Instruction>::value,
  331. "Structure does not have standard layout");
  332. } // namespace Shader
  333. } // namespace Tegra