diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 297 |
2 files changed, 298 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index a710c4bc5..4defb5786 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -9,6 +9,7 @@ add_library(video_core STATIC | |||
| 9 | engines/maxwell_3d.h | 9 | engines/maxwell_3d.h |
| 10 | engines/maxwell_compute.cpp | 10 | engines/maxwell_compute.cpp |
| 11 | engines/maxwell_compute.h | 11 | engines/maxwell_compute.h |
| 12 | engines/shader_bytecode.h | ||
| 12 | gpu.cpp | 13 | gpu.cpp |
| 13 | gpu.h | 14 | gpu.h |
| 14 | macro_interpreter.cpp | 15 | macro_interpreter.cpp |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h new file mode 100644 index 000000000..6660742cc --- /dev/null +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -0,0 +1,297 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <map> | ||
| 8 | #include <string> | ||
| 9 | #include "common/bit_field.h" | ||
| 10 | |||
| 11 | namespace Tegra { | ||
| 12 | namespace Shader { | ||
| 13 | |||
| 14 | struct Register { | ||
| 15 | constexpr Register() = default; | ||
| 16 | |||
| 17 | constexpr Register(u64 value) : value(value) {} | ||
| 18 | |||
| 19 | constexpr u64 GetIndex() const { | ||
| 20 | return value; | ||
| 21 | } | ||
| 22 | |||
| 23 | constexpr operator u64() const { | ||
| 24 | return value; | ||
| 25 | } | ||
| 26 | |||
| 27 | template <typename T> | ||
| 28 | constexpr u64 operator-(const T& oth) const { | ||
| 29 | return value - oth; | ||
| 30 | } | ||
| 31 | |||
| 32 | template <typename T> | ||
| 33 | constexpr u64 operator&(const T& oth) const { | ||
| 34 | return value & oth; | ||
| 35 | } | ||
| 36 | |||
| 37 | constexpr u64 operator&(const Register& oth) const { | ||
| 38 | return value & oth.value; | ||
| 39 | } | ||
| 40 | |||
| 41 | constexpr u64 operator~() const { | ||
| 42 | return ~value; | ||
| 43 | } | ||
| 44 | |||
| 45 | private: | ||
| 46 | u64 value; | ||
| 47 | }; | ||
| 48 | |||
| 49 | union Attribute { | ||
| 50 | constexpr Attribute() = default; | ||
| 51 | |||
| 52 | constexpr Attribute(u64 value) : value(value) {} | ||
| 53 | |||
| 54 | enum class Index : u64 { | ||
| 55 | Position = 7, | ||
| 56 | Attribute_0 = 8, | ||
| 57 | }; | ||
| 58 | |||
| 59 | constexpr Index GetIndex() const { | ||
| 60 | return index; | ||
| 61 | } | ||
| 62 | |||
| 63 | public: | ||
| 64 | BitField<24, 6, Index> index; | ||
| 65 | BitField<22, 2, u64> element; | ||
| 66 | BitField<39, 8, u64> reg; | ||
| 67 | BitField<47, 3, u64> size; | ||
| 68 | u64 value; | ||
| 69 | }; | ||
| 70 | |||
| 71 | union Uniform { | ||
| 72 | BitField<20, 14, u64> offset; | ||
| 73 | BitField<34, 5, u64> index; | ||
| 74 | }; | ||
| 75 | |||
| 76 | union OpCode { | ||
| 77 | enum class Id : u64 { | ||
| 78 | TEXS = 0x6C, | ||
| 79 | IPA = 0xE0, | ||
| 80 | FFMA_IMM = 0x65, | ||
| 81 | FFMA_CR = 0x93, | ||
| 82 | FFMA_RC = 0xA3, | ||
| 83 | FFMA_RR = 0xB3, | ||
| 84 | |||
| 85 | FADD_C = 0x98B, | ||
| 86 | FMUL_C = 0x98D, | ||
| 87 | MUFU = 0xA10, | ||
| 88 | FADD_R = 0xB8B, | ||
| 89 | FMUL_R = 0xB8D, | ||
| 90 | LD_A = 0x1DFB, | ||
| 91 | ST_A = 0x1DFE, | ||
| 92 | |||
| 93 | FSETP_R = 0x5BB, | ||
| 94 | FSETP_C = 0x4BB, | ||
| 95 | EXIT = 0xE30, | ||
| 96 | KIL = 0xE33, | ||
| 97 | |||
| 98 | FMUL_IMM = 0x70D, | ||
| 99 | FMUL_IMM_x = 0x72D, | ||
| 100 | FADD_IMM = 0x70B, | ||
| 101 | FADD_IMM_x = 0x72B, | ||
| 102 | }; | ||
| 103 | |||
| 104 | enum class Type { | ||
| 105 | Trivial, | ||
| 106 | Arithmetic, | ||
| 107 | Flow, | ||
| 108 | Memory, | ||
| 109 | Unknown, | ||
| 110 | }; | ||
| 111 | |||
| 112 | struct Info { | ||
| 113 | Type type; | ||
| 114 | std::string name; | ||
| 115 | }; | ||
| 116 | |||
| 117 | constexpr OpCode() = default; | ||
| 118 | |||
| 119 | constexpr OpCode(Id value) : value(static_cast<u64>(value)) {} | ||
| 120 | |||
| 121 | constexpr OpCode(u64 value) : value{value} {} | ||
| 122 | |||
| 123 | constexpr Id EffectiveOpCode() const { | ||
| 124 | switch (op1) { | ||
| 125 | case Id::TEXS: | ||
| 126 | return op1; | ||
| 127 | } | ||
| 128 | |||
| 129 | switch (op2) { | ||
| 130 | case Id::IPA: | ||
| 131 | return op2; | ||
| 132 | } | ||
| 133 | |||
| 134 | switch (op3) { | ||
| 135 | case Id::FFMA_IMM: | ||
| 136 | case Id::FFMA_CR: | ||
| 137 | case Id::FFMA_RC: | ||
| 138 | case Id::FFMA_RR: | ||
| 139 | return op3; | ||
| 140 | } | ||
| 141 | |||
| 142 | switch (op4) { | ||
| 143 | case Id::EXIT: | ||
| 144 | case Id::FSETP_R: | ||
| 145 | case Id::FSETP_C: | ||
| 146 | case Id::KIL: | ||
| 147 | return op4; | ||
| 148 | } | ||
| 149 | |||
| 150 | switch (op5) { | ||
| 151 | case Id::MUFU: | ||
| 152 | case Id::LD_A: | ||
| 153 | case Id::ST_A: | ||
| 154 | case Id::FADD_R: | ||
| 155 | case Id::FADD_C: | ||
| 156 | case Id::FMUL_R: | ||
| 157 | case Id::FMUL_C: | ||
| 158 | return op5; | ||
| 159 | |||
| 160 | case Id::FMUL_IMM: | ||
| 161 | case Id::FMUL_IMM_x: | ||
| 162 | return Id::FMUL_IMM; | ||
| 163 | |||
| 164 | case Id::FADD_IMM: | ||
| 165 | case Id::FADD_IMM_x: | ||
| 166 | return Id::FADD_IMM; | ||
| 167 | } | ||
| 168 | |||
| 169 | return static_cast<Id>(value); | ||
| 170 | } | ||
| 171 | |||
| 172 | static const Info& GetInfo(const OpCode& opcode) { | ||
| 173 | static const std::map<Id, Info> info_table{BuildInfoTable()}; | ||
| 174 | const auto& search{info_table.find(opcode.EffectiveOpCode())}; | ||
| 175 | if (search != info_table.end()) { | ||
| 176 | return search->second; | ||
| 177 | } | ||
| 178 | |||
| 179 | static const Info unknown{Type::Unknown, "UNK"}; | ||
| 180 | return unknown; | ||
| 181 | } | ||
| 182 | |||
| 183 | constexpr operator Id() const { | ||
| 184 | return static_cast<Id>(value); | ||
| 185 | } | ||
| 186 | |||
| 187 | constexpr OpCode operator<<(size_t bits) const { | ||
| 188 | return value << bits; | ||
| 189 | } | ||
| 190 | |||
| 191 | constexpr OpCode operator>>(size_t bits) const { | ||
| 192 | return value >> bits; | ||
| 193 | } | ||
| 194 | |||
| 195 | template <typename T> | ||
| 196 | constexpr u64 operator-(const T& oth) const { | ||
| 197 | return value - oth; | ||
| 198 | } | ||
| 199 | |||
| 200 | constexpr u64 operator&(const OpCode& oth) const { | ||
| 201 | return value & oth.value; | ||
| 202 | } | ||
| 203 | |||
| 204 | constexpr u64 operator~() const { | ||
| 205 | return ~value; | ||
| 206 | } | ||
| 207 | |||
| 208 | static std::map<Id, Info> BuildInfoTable() { | ||
| 209 | std::map<Id, Info> info_table; | ||
| 210 | info_table[Id::TEXS] = {Type::Memory, "texs"}; | ||
| 211 | info_table[Id::LD_A] = {Type::Memory, "ld_a"}; | ||
| 212 | info_table[Id::ST_A] = {Type::Memory, "st_a"}; | ||
| 213 | info_table[Id::IPA] = {Type::Arithmetic, "ipa"}; | ||
| 214 | info_table[Id::MUFU] = {Type::Arithmetic, "mufu"}; | ||
| 215 | info_table[Id::FFMA_IMM] = {Type::Arithmetic, "ffma_imm"}; | ||
| 216 | info_table[Id::FFMA_CR] = {Type::Arithmetic, "ffma_cr"}; | ||
| 217 | info_table[Id::FFMA_RC] = {Type::Arithmetic, "ffma_rc"}; | ||
| 218 | info_table[Id::FFMA_RR] = {Type::Arithmetic, "ffma_rr"}; | ||
| 219 | info_table[Id::FADD_R] = {Type::Arithmetic, "fadd_r"}; | ||
| 220 | info_table[Id::FADD_C] = {Type::Arithmetic, "fadd_c"}; | ||
| 221 | info_table[Id::FADD_IMM] = {Type::Arithmetic, "fadd_imm"}; | ||
| 222 | info_table[Id::FMUL_R] = {Type::Arithmetic, "fmul_r"}; | ||
| 223 | info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"}; | ||
| 224 | info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"}; | ||
| 225 | info_table[Id::EXIT] = {Type::Trivial, "exit"}; | ||
| 226 | return info_table; | ||
| 227 | } | ||
| 228 | |||
| 229 | BitField<57, 7, Id> op1; | ||
| 230 | BitField<56, 8, Id> op2; | ||
| 231 | BitField<55, 9, Id> op3; | ||
| 232 | BitField<52, 12, Id> op4; | ||
| 233 | BitField<51, 13, Id> op5; | ||
| 234 | u64 value; | ||
| 235 | }; | ||
| 236 | static_assert(sizeof(OpCode) == 0x8, "Incorrect structure size"); | ||
| 237 | |||
| 238 | } // namespace Shader | ||
| 239 | } // namespace Tegra | ||
| 240 | |||
| 241 | namespace std { | ||
| 242 | |||
| 243 | template <> | ||
| 244 | struct make_unsigned<Tegra::Shader::Attribute> { | ||
| 245 | using type = Tegra::Shader::Attribute; | ||
| 246 | }; | ||
| 247 | |||
| 248 | template <> | ||
| 249 | struct make_unsigned<Tegra::Shader::Register> { | ||
| 250 | using type = Tegra::Shader::Register; | ||
| 251 | }; | ||
| 252 | |||
| 253 | template <> | ||
| 254 | struct make_unsigned<Tegra::Shader::OpCode> { | ||
| 255 | using type = Tegra::Shader::OpCode; | ||
| 256 | }; | ||
| 257 | |||
| 258 | } // namespace std | ||
| 259 | |||
| 260 | namespace Tegra { | ||
| 261 | namespace Shader { | ||
| 262 | |||
| 263 | enum class Pred : u64 { | ||
| 264 | UnusedIndex = 0x7, | ||
| 265 | NeverExecute = 0xf, | ||
| 266 | }; | ||
| 267 | |||
| 268 | #pragma pack(1) | ||
| 269 | union Instruction { | ||
| 270 | Instruction& operator=(const Instruction& instr) { | ||
| 271 | hex = instr.hex; | ||
| 272 | return *this; | ||
| 273 | } | ||
| 274 | |||
| 275 | OpCode opcode; | ||
| 276 | BitField<0, 8, Register> gpr1; | ||
| 277 | BitField<8, 8, Register> gpr2; | ||
| 278 | BitField<16, 4, Pred> pred; | ||
| 279 | BitField<39, 8, Register> gpr3; | ||
| 280 | BitField<45, 1, u64> nb; | ||
| 281 | BitField<46, 1, u64> aa; | ||
| 282 | BitField<48, 1, u64> na; | ||
| 283 | BitField<49, 1, u64> ab; | ||
| 284 | BitField<50, 1, u64> ad; | ||
| 285 | Attribute attribute; | ||
| 286 | Uniform uniform; | ||
| 287 | |||
| 288 | u64 hex; | ||
| 289 | }; | ||
| 290 | static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size"); | ||
| 291 | static_assert(std::is_standard_layout<Instruction>::value, | ||
| 292 | "Structure does not have standard layout"); | ||
| 293 | |||
| 294 | #pragma pack() | ||
| 295 | |||
| 296 | } // namespace Shader | ||
| 297 | } // namespace Tegra | ||