summaryrefslogtreecommitdiffstats
path: root/src/video_core/engines
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-04-05 03:43:40 +0200
committerbunnei <bunneidev@gmail.com>2018-04-14 05:48:19 +0200
commit4e7e0f81125f30a108b90c5ee6cae9b248164d9e (patch)
tree8a8eb7080b1cfb7f464578072df4efe97ab05a95 /src/video_core/engines
parentbit_field: Make all methods constexpr. (diff)
downloadyuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.tar
yuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.tar.gz
yuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.tar.bz2
yuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.tar.lz
yuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.tar.xz
yuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.tar.zst
yuzu-4e7e0f81125f30a108b90c5ee6cae9b248164d9e.zip
Diffstat (limited to 'src/video_core/engines')
-rw-r--r--src/video_core/engines/shader_bytecode.h297
1 files changed, 297 insertions, 0 deletions
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 @@
+// Copyright 2018 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <map>
+#include <string>
+#include "common/bit_field.h"
+
+namespace Tegra {
+namespace Shader {
+
+struct Register {
+ constexpr Register() = default;
+
+ constexpr Register(u64 value) : value(value) {}
+
+ constexpr u64 GetIndex() const {
+ return value;
+ }
+
+ constexpr operator u64() const {
+ return value;
+ }
+
+ template <typename T>
+ constexpr u64 operator-(const T& oth) const {
+ return value - oth;
+ }
+
+ template <typename T>
+ constexpr u64 operator&(const T& oth) const {
+ return value & oth;
+ }
+
+ constexpr u64 operator&(const Register& oth) const {
+ return value & oth.value;
+ }
+
+ constexpr u64 operator~() const {
+ return ~value;
+ }
+
+private:
+ u64 value;
+};
+
+union Attribute {
+ constexpr Attribute() = default;
+
+ constexpr Attribute(u64 value) : value(value) {}
+
+ enum class Index : u64 {
+ Position = 7,
+ Attribute_0 = 8,
+ };
+
+ constexpr Index GetIndex() const {
+ return index;
+ }
+
+public:
+ BitField<24, 6, Index> index;
+ BitField<22, 2, u64> element;
+ BitField<39, 8, u64> reg;
+ BitField<47, 3, u64> size;
+ u64 value;
+};
+
+union Uniform {
+ BitField<20, 14, u64> offset;
+ BitField<34, 5, u64> index;
+};
+
+union OpCode {
+ enum class Id : u64 {
+ TEXS = 0x6C,
+ IPA = 0xE0,
+ FFMA_IMM = 0x65,
+ FFMA_CR = 0x93,
+ FFMA_RC = 0xA3,
+ FFMA_RR = 0xB3,
+
+ FADD_C = 0x98B,
+ FMUL_C = 0x98D,
+ MUFU = 0xA10,
+ FADD_R = 0xB8B,
+ FMUL_R = 0xB8D,
+ LD_A = 0x1DFB,
+ ST_A = 0x1DFE,
+
+ FSETP_R = 0x5BB,
+ FSETP_C = 0x4BB,
+ EXIT = 0xE30,
+ KIL = 0xE33,
+
+ FMUL_IMM = 0x70D,
+ FMUL_IMM_x = 0x72D,
+ FADD_IMM = 0x70B,
+ FADD_IMM_x = 0x72B,
+ };
+
+ enum class Type {
+ Trivial,
+ Arithmetic,
+ Flow,
+ Memory,
+ Unknown,
+ };
+
+ struct Info {
+ Type type;
+ std::string name;
+ };
+
+ constexpr OpCode() = default;
+
+ constexpr OpCode(Id value) : value(static_cast<u64>(value)) {}
+
+ constexpr OpCode(u64 value) : value{value} {}
+
+ constexpr Id EffectiveOpCode() const {
+ switch (op1) {
+ case Id::TEXS:
+ return op1;
+ }
+
+ switch (op2) {
+ case Id::IPA:
+ return op2;
+ }
+
+ switch (op3) {
+ case Id::FFMA_IMM:
+ case Id::FFMA_CR:
+ case Id::FFMA_RC:
+ case Id::FFMA_RR:
+ return op3;
+ }
+
+ switch (op4) {
+ case Id::EXIT:
+ case Id::FSETP_R:
+ case Id::FSETP_C:
+ case Id::KIL:
+ return op4;
+ }
+
+ switch (op5) {
+ case Id::MUFU:
+ case Id::LD_A:
+ case Id::ST_A:
+ case Id::FADD_R:
+ case Id::FADD_C:
+ case Id::FMUL_R:
+ case Id::FMUL_C:
+ return op5;
+
+ case Id::FMUL_IMM:
+ case Id::FMUL_IMM_x:
+ return Id::FMUL_IMM;
+
+ case Id::FADD_IMM:
+ case Id::FADD_IMM_x:
+ return Id::FADD_IMM;
+ }
+
+ return static_cast<Id>(value);
+ }
+
+ static const Info& GetInfo(const OpCode& opcode) {
+ static const std::map<Id, Info> info_table{BuildInfoTable()};
+ const auto& search{info_table.find(opcode.EffectiveOpCode())};
+ if (search != info_table.end()) {
+ return search->second;
+ }
+
+ static const Info unknown{Type::Unknown, "UNK"};
+ return unknown;
+ }
+
+ constexpr operator Id() const {
+ return static_cast<Id>(value);
+ }
+
+ constexpr OpCode operator<<(size_t bits) const {
+ return value << bits;
+ }
+
+ constexpr OpCode operator>>(size_t bits) const {
+ return value >> bits;
+ }
+
+ template <typename T>
+ constexpr u64 operator-(const T& oth) const {
+ return value - oth;
+ }
+
+ constexpr u64 operator&(const OpCode& oth) const {
+ return value & oth.value;
+ }
+
+ constexpr u64 operator~() const {
+ return ~value;
+ }
+
+ static std::map<Id, Info> BuildInfoTable() {
+ std::map<Id, Info> info_table;
+ info_table[Id::TEXS] = {Type::Memory, "texs"};
+ info_table[Id::LD_A] = {Type::Memory, "ld_a"};
+ info_table[Id::ST_A] = {Type::Memory, "st_a"};
+ info_table[Id::IPA] = {Type::Arithmetic, "ipa"};
+ info_table[Id::MUFU] = {Type::Arithmetic, "mufu"};
+ info_table[Id::FFMA_IMM] = {Type::Arithmetic, "ffma_imm"};
+ info_table[Id::FFMA_CR] = {Type::Arithmetic, "ffma_cr"};
+ info_table[Id::FFMA_RC] = {Type::Arithmetic, "ffma_rc"};
+ info_table[Id::FFMA_RR] = {Type::Arithmetic, "ffma_rr"};
+ info_table[Id::FADD_R] = {Type::Arithmetic, "fadd_r"};
+ info_table[Id::FADD_C] = {Type::Arithmetic, "fadd_c"};
+ info_table[Id::FADD_IMM] = {Type::Arithmetic, "fadd_imm"};
+ info_table[Id::FMUL_R] = {Type::Arithmetic, "fmul_r"};
+ info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"};
+ info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"};
+ info_table[Id::EXIT] = {Type::Trivial, "exit"};
+ return info_table;
+ }
+
+ BitField<57, 7, Id> op1;
+ BitField<56, 8, Id> op2;
+ BitField<55, 9, Id> op3;
+ BitField<52, 12, Id> op4;
+ BitField<51, 13, Id> op5;
+ u64 value;
+};
+static_assert(sizeof(OpCode) == 0x8, "Incorrect structure size");
+
+} // namespace Shader
+} // namespace Tegra
+
+namespace std {
+
+template <>
+struct make_unsigned<Tegra::Shader::Attribute> {
+ using type = Tegra::Shader::Attribute;
+};
+
+template <>
+struct make_unsigned<Tegra::Shader::Register> {
+ using type = Tegra::Shader::Register;
+};
+
+template <>
+struct make_unsigned<Tegra::Shader::OpCode> {
+ using type = Tegra::Shader::OpCode;
+};
+
+} // namespace std
+
+namespace Tegra {
+namespace Shader {
+
+enum class Pred : u64 {
+ UnusedIndex = 0x7,
+ NeverExecute = 0xf,
+};
+
+#pragma pack(1)
+union Instruction {
+ Instruction& operator=(const Instruction& instr) {
+ hex = instr.hex;
+ return *this;
+ }
+
+ OpCode opcode;
+ BitField<0, 8, Register> gpr1;
+ BitField<8, 8, Register> gpr2;
+ BitField<16, 4, Pred> pred;
+ BitField<39, 8, Register> gpr3;
+ BitField<45, 1, u64> nb;
+ BitField<46, 1, u64> aa;
+ BitField<48, 1, u64> na;
+ BitField<49, 1, u64> ab;
+ BitField<50, 1, u64> ad;
+ Attribute attribute;
+ Uniform uniform;
+
+ u64 hex;
+};
+static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size");
+static_assert(std::is_standard_layout<Instruction>::value,
+ "Structure does not have standard layout");
+
+#pragma pack()
+
+} // namespace Shader
+} // namespace Tegra