diff options
Diffstat (limited to 'src/video_core')
| -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      engines/maxwell_3d.h      engines/maxwell_compute.cpp      engines/maxwell_compute.h +    engines/shader_bytecode.h      gpu.cpp      gpu.h      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 @@ +// 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 | 
