From 4e7e0f81125f30a108b90c5ee6cae9b248164d9e Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 4 Apr 2018 21:43:40 -0400 Subject: shader_bytecode: Add initial module for shader decoding. --- src/video_core/engines/shader_bytecode.h | 297 +++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/video_core/engines/shader_bytecode.h (limited to 'src/video_core/engines') 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 +#include +#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 + constexpr u64 operator-(const T& oth) const { + return value - oth; + } + + template + 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(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(value); + } + + static const Info& GetInfo(const OpCode& opcode) { + static const std::map 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(value); + } + + constexpr OpCode operator<<(size_t bits) const { + return value << bits; + } + + constexpr OpCode operator>>(size_t bits) const { + return value >> bits; + } + + template + 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 BuildInfoTable() { + std::map 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 { + using type = Tegra::Shader::Attribute; +}; + +template <> +struct make_unsigned { + using type = Tegra::Shader::Register; +}; + +template <> +struct make_unsigned { + 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::value, + "Structure does not have standard layout"); + +#pragma pack() + +} // namespace Shader +} // namespace Tegra -- cgit v1.2.3 From 33bb53571bf7ca394fa8b6d5107e8dfb5758f1d2 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 7 Apr 2018 23:14:41 -0400 Subject: maxwell_3d: Fix shader_config decodings. --- src/video_core/engines/maxwell_3d.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 98b39b2ff..528bb31d3 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -427,14 +427,11 @@ public: BitField<0, 1, u32> enable; BitField<4, 4, ShaderProgram> program; }; - u32 start_id; - INSERT_PADDING_WORDS(1); - u32 gpr_alloc; - ShaderStage type; - INSERT_PADDING_WORDS(9); + u32 offset; + INSERT_PADDING_WORDS(14); } shader_config[MaxShaderProgram]; - INSERT_PADDING_WORDS(0x8C); + INSERT_PADDING_WORDS(0x80); struct { u32 cb_size; -- cgit v1.2.3 From 35aca0bf1f22379c82f26edade0d18eb47565cf4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 7 Apr 2018 23:24:50 -0400 Subject: maxwell_3d: Make memory_manager public. --- src/video_core/engines/maxwell_3d.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 528bb31d3..9c6236c39 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -504,6 +504,7 @@ public: }; State state{}; + MemoryManager& memory_manager; /// Reads a register value located at the input method address u32 GetRegisterValue(u32 method) const; @@ -518,8 +519,6 @@ public: std::vector GetStageTextures(Regs::ShaderStage stage) const; private: - MemoryManager& memory_manager; - std::unordered_map> uploaded_macros; /// Macro method that is currently being executed / being fed parameters. -- cgit v1.2.3 From 5a47832221fb03a50af2583ec311114871ea1dd1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Apr 2018 22:09:23 -0400 Subject: shader_bytecode: Add SubOp decoding. --- src/video_core/engines/shader_bytecode.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 6660742cc..477d01f94 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -265,6 +265,15 @@ enum class Pred : u64 { NeverExecute = 0xf, }; +enum class SubOp : u64 { + Cos = 0x0, + Sin = 0x1, + Ex2 = 0x2, + Lg2 = 0x3, + Rcp = 0x4, + Rsq = 0x5, +}; + #pragma pack(1) union Instruction { Instruction& operator=(const Instruction& instr) { @@ -276,6 +285,7 @@ union Instruction { BitField<0, 8, Register> gpr1; BitField<8, 8, Register> gpr2; BitField<16, 4, Pred> pred; + BitField<20, 7, SubOp> sub_op; BitField<39, 8, Register> gpr3; BitField<45, 1, u64> nb; BitField<46, 1, u64> aa; -- cgit v1.2.3 From 7639667562ae155d27b5f5fcec9a54b0c17c1682 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Apr 2018 22:10:17 -0400 Subject: shader_bytecode: Add FSETP and KIL to GetInfo. --- src/video_core/engines/shader_bytecode.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 477d01f94..a4d02e572 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -222,7 +222,10 @@ union OpCode { 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::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; + info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; info_table[Id::EXIT] = {Type::Trivial, "exit"}; + info_table[Id::KIL] = {Type::Flow, "kil"}; return info_table; } -- cgit v1.2.3 From 86135864da9bbbd5906e96862994bd24f3cd4da5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Apr 2018 23:39:44 -0400 Subject: gl_shader_decompiler: Implement negate, abs, etc. and lots of cleanup. --- src/video_core/engines/shader_bytecode.h | 59 +++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 20 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index a4d02e572..dbcd23755 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -56,15 +56,18 @@ union Attribute { Attribute_0 = 8, }; - constexpr Index GetIndex() const { - return index; - } + union { + BitField<22, 2, u64> element; + BitField<24, 6, Index> index; + BitField<47, 3, u64> size; + } fmt20; + + union { + BitField<30, 2, u64> element; + BitField<32, 6, Index> index; + } fmt28; -public: - BitField<24, 6, Index> index; - BitField<22, 2, u64> element; BitField<39, 8, u64> reg; - BitField<47, 3, u64> size; u64 value; }; @@ -104,6 +107,7 @@ union OpCode { enum class Type { Trivial, Arithmetic, + Ffma, Flow, Memory, Unknown, @@ -210,12 +214,11 @@ union OpCode { 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::FFMA_IMM] = {Type::Ffma, "ffma_imm"}; + info_table[Id::FFMA_CR] = {Type::Ffma, "ffma_cr"}; + info_table[Id::FFMA_RC] = {Type::Ffma, "ffma_rc"}; + info_table[Id::FFMA_RR] = {Type::Ffma, "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"}; @@ -225,6 +228,7 @@ union OpCode { info_table[Id::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; info_table[Id::EXIT] = {Type::Trivial, "exit"}; + info_table[Id::IPA] = {Type::Trivial, "ipa"}; info_table[Id::KIL] = {Type::Flow, "kil"}; return info_table; } @@ -285,16 +289,31 @@ union Instruction { } OpCode opcode; - BitField<0, 8, Register> gpr1; - BitField<8, 8, Register> gpr2; + BitField<0, 8, Register> gpr0; + BitField<8, 8, Register> gpr8; BitField<16, 4, Pred> pred; + BitField<20, 8, Register> gpr20; BitField<20, 7, SubOp> sub_op; - 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; + BitField<28, 8, Register> gpr28; + BitField<36, 13, u64> imm36; + BitField<39, 8, Register> gpr39; + + union { + BitField<45, 1, u64> negate_b; + BitField<46, 1, u64> abs_a; + BitField<48, 1, u64> negate_a; + BitField<49, 1, u64> abs_b; + BitField<50, 1, u64> abs_d; + } alu; + + union { + BitField<48, 1, u64> negate_b; + BitField<49, 1, u64> negate_c; + } ffma; + + BitField<60, 1, u64> is_b_gpr; + BitField<59, 1, u64> is_c_gpr; + Attribute attribute; Uniform uniform; -- cgit v1.2.3 From 0d408b965b971c2b8df9a6e4c1cd1d7a8e9dc5d1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 14 Apr 2018 14:09:32 -0400 Subject: shaders: Fix GCC and clang build issues. --- src/video_core/engines/shader_bytecode.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index dbcd23755..e285d097d 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -12,7 +12,7 @@ namespace Tegra { namespace Shader { struct Register { - constexpr Register() = default; + Register() = default; constexpr Register(u64 value) : value(value) {} @@ -47,7 +47,7 @@ private: }; union Attribute { - constexpr Attribute() = default; + Attribute() = default; constexpr Attribute(u64 value) : value(value) {} @@ -118,7 +118,7 @@ union OpCode { std::string name; }; - constexpr OpCode() = default; + OpCode() = default; constexpr OpCode(Id value) : value(static_cast(value)) {} -- cgit v1.2.3 From e6224fec275a725bfbb261003c9db44a3da475df Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 14 Apr 2018 15:57:58 -0400 Subject: shaders: Address PR review feedback. --- src/video_core/engines/shader_bytecode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e285d097d..98af381df 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -247,6 +247,7 @@ static_assert(sizeof(OpCode) == 0x8, "Incorrect structure size"); namespace std { +// TODO(bunne): The below is forbidden by the C++ standard, but works fine. See #330. template <> struct make_unsigned { using type = Tegra::Shader::Attribute; @@ -281,7 +282,6 @@ enum class SubOp : u64 { Rsq = 0x5, }; -#pragma pack(1) union Instruction { Instruction& operator=(const Instruction& instr) { hex = instr.hex; -- cgit v1.2.3 From 1b41b875dcd24c662b947731f48f4d1c7131fa0b Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 14 Apr 2018 18:50:06 -0400 Subject: shaders: Add NumTextureSamplers const, remove unused #pragma. --- src/video_core/engines/shader_bytecode.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/video_core/engines') diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 98af381df..eff0c35a1 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -323,7 +323,5 @@ static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size"); static_assert(std::is_standard_layout::value, "Structure does not have standard layout"); -#pragma pack() - } // namespace Shader } // namespace Tegra -- cgit v1.2.3