diff options
| author | 2018-12-20 19:09:21 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:49 -0300 | |
| commit | 15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71 (patch) | |
| tree | a365dda91981122a62024f371f4f00d5b2035ad6 /src | |
| parent | shader_bytecode: Fixup encoding (diff) | |
| download | yuzu-15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71.tar.gz yuzu-15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71.tar.xz yuzu-15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71.zip | |
shader_ir: Initial implementation
Diffstat (limited to 'src')
30 files changed, 1573 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 327db68a5..e9e324386 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -59,6 +59,33 @@ add_library(video_core STATIC | |||
| 59 | renderer_opengl/renderer_opengl.h | 59 | renderer_opengl/renderer_opengl.h |
| 60 | renderer_opengl/utils.cpp | 60 | renderer_opengl/utils.cpp |
| 61 | renderer_opengl/utils.h | 61 | renderer_opengl/utils.h |
| 62 | shader/decode/arithmetic.cpp | ||
| 63 | shader/decode/arithmetic_immediate.cpp | ||
| 64 | shader/decode/bfe.cpp | ||
| 65 | shader/decode/bfi.cpp | ||
| 66 | shader/decode/shift.cpp | ||
| 67 | shader/decode/arithmetic_integer.cpp | ||
| 68 | shader/decode/arithmetic_integer_immediate.cpp | ||
| 69 | shader/decode/arithmetic_half.cpp | ||
| 70 | shader/decode/arithmetic_half_immediate.cpp | ||
| 71 | shader/decode/ffma.cpp | ||
| 72 | shader/decode/hfma2.cpp | ||
| 73 | shader/decode/conversion.cpp | ||
| 74 | shader/decode/memory.cpp | ||
| 75 | shader/decode/float_set_predicate.cpp | ||
| 76 | shader/decode/integer_set_predicate.cpp | ||
| 77 | shader/decode/half_set_predicate.cpp | ||
| 78 | shader/decode/predicate_set_register.cpp | ||
| 79 | shader/decode/predicate_set_predicate.cpp | ||
| 80 | shader/decode/register_set_predicate.cpp | ||
| 81 | shader/decode/float_set.cpp | ||
| 82 | shader/decode/integer_set.cpp | ||
| 83 | shader/decode/half_set.cpp | ||
| 84 | shader/decode/xmad.cpp | ||
| 85 | shader/decode/other.cpp | ||
| 86 | shader/decode.cpp | ||
| 87 | shader/shader_ir.cpp | ||
| 88 | shader/shader_ir.h | ||
| 62 | surface.cpp | 89 | surface.cpp |
| 63 | surface.h | 90 | surface.h |
| 64 | textures/astc.cpp | 91 | textures/astc.cpp |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e62b66acd..b1e0d763e 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -397,6 +397,10 @@ struct IpaMode { | |||
| 397 | bool operator!=(const IpaMode& a) const { | 397 | bool operator!=(const IpaMode& a) const { |
| 398 | return !operator==(a); | 398 | return !operator==(a); |
| 399 | } | 399 | } |
| 400 | bool operator<(const IpaMode& a) const { | ||
| 401 | return std::tie(interpolation_mode, sampling_mode) < | ||
| 402 | std::tie(a.interpolation_mode, a.sampling_mode); | ||
| 403 | } | ||
| 400 | }; | 404 | }; |
| 401 | 405 | ||
| 402 | enum class SystemVariable : u64 { | 406 | enum class SystemVariable : u64 { |
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp new file mode 100644 index 000000000..c973328ab --- /dev/null +++ b/src/video_core/shader/decode.cpp | |||
| @@ -0,0 +1,199 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cstring> | ||
| 6 | #include <set> | ||
| 7 | |||
| 8 | #include <fmt/format.h> | ||
| 9 | |||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "video_core/engines/shader_bytecode.h" | ||
| 12 | #include "video_core/engines/shader_header.h" | ||
| 13 | #include "video_core/shader/shader_ir.h" | ||
| 14 | |||
| 15 | namespace VideoCommon::Shader { | ||
| 16 | |||
| 17 | using Tegra::Shader::Instruction; | ||
| 18 | using Tegra::Shader::OpCode; | ||
| 19 | |||
| 20 | /// Merges exit method of two parallel branches. | ||
| 21 | constexpr ExitMethod ParallelExit(ExitMethod a, ExitMethod b) { | ||
| 22 | if (a == ExitMethod::Undetermined) { | ||
| 23 | return b; | ||
| 24 | } | ||
| 25 | if (b == ExitMethod::Undetermined) { | ||
| 26 | return a; | ||
| 27 | } | ||
| 28 | if (a == b) { | ||
| 29 | return a; | ||
| 30 | } | ||
| 31 | return ExitMethod::Conditional; | ||
| 32 | } | ||
| 33 | |||
| 34 | /** | ||
| 35 | * Returns whether the instruction at the specified offset is a 'sched' instruction. | ||
| 36 | * Sched instructions always appear before a sequence of 3 instructions. | ||
| 37 | */ | ||
| 38 | constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) { | ||
| 39 | constexpr u32 SchedPeriod = 4; | ||
| 40 | u32 absolute_offset = offset - main_offset; | ||
| 41 | |||
| 42 | return (absolute_offset % SchedPeriod) == 0; | ||
| 43 | } | ||
| 44 | |||
| 45 | void ShaderIR::Decode() { | ||
| 46 | std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); | ||
| 47 | |||
| 48 | std::set<u32> labels; | ||
| 49 | const ExitMethod exit_method = Scan(main_offset, MAX_PROGRAM_LENGTH, labels); | ||
| 50 | if (exit_method != ExitMethod::AlwaysEnd) { | ||
| 51 | UNREACHABLE_MSG("Program does not always end"); | ||
| 52 | } | ||
| 53 | |||
| 54 | if (labels.empty()) { | ||
| 55 | basic_blocks.insert({main_offset, DecodeRange(main_offset, MAX_PROGRAM_LENGTH)}); | ||
| 56 | return; | ||
| 57 | } | ||
| 58 | |||
| 59 | labels.insert(main_offset); | ||
| 60 | |||
| 61 | for (const u32 label : labels) { | ||
| 62 | const auto next_it = labels.lower_bound(label + 1); | ||
| 63 | const u32 next_label = next_it == labels.end() ? MAX_PROGRAM_LENGTH : *next_it; | ||
| 64 | |||
| 65 | basic_blocks.insert({label, DecodeRange(label, next_label)}); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | ExitMethod ShaderIR::Scan(u32 begin, u32 end, std::set<u32>& labels) { | ||
| 70 | const auto [iter, inserted] = | ||
| 71 | exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined); | ||
| 72 | ExitMethod& exit_method = iter->second; | ||
| 73 | if (!inserted) | ||
| 74 | return exit_method; | ||
| 75 | |||
| 76 | for (u32 offset = begin; offset != end && offset != MAX_PROGRAM_LENGTH; ++offset) { | ||
| 77 | coverage_begin = std::min(coverage_begin, offset); | ||
| 78 | coverage_end = std::max(coverage_end, offset + 1); | ||
| 79 | |||
| 80 | const Instruction instr = {program_code[offset]}; | ||
| 81 | const auto opcode = OpCode::Decode(instr); | ||
| 82 | if (!opcode) | ||
| 83 | continue; | ||
| 84 | switch (opcode->get().GetId()) { | ||
| 85 | case OpCode::Id::EXIT: { | ||
| 86 | // The EXIT instruction can be predicated, which means that the shader can conditionally | ||
| 87 | // end on this instruction. We have to consider the case where the condition is not met | ||
| 88 | // and check the exit method of that other basic block. | ||
| 89 | using Tegra::Shader::Pred; | ||
| 90 | if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { | ||
| 91 | return exit_method = ExitMethod::AlwaysEnd; | ||
| 92 | } else { | ||
| 93 | const ExitMethod not_met = Scan(offset + 1, end, labels); | ||
| 94 | return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | case OpCode::Id::BRA: { | ||
| 98 | const u32 target = offset + instr.bra.GetBranchTarget(); | ||
| 99 | labels.insert(target); | ||
| 100 | const ExitMethod no_jmp = Scan(offset + 1, end, labels); | ||
| 101 | const ExitMethod jmp = Scan(target, end, labels); | ||
| 102 | return exit_method = ParallelExit(no_jmp, jmp); | ||
| 103 | } | ||
| 104 | case OpCode::Id::SSY: | ||
| 105 | case OpCode::Id::PBK: { | ||
| 106 | // The SSY and PBK use a similar encoding as the BRA instruction. | ||
| 107 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | ||
| 108 | "Constant buffer branching is not supported"); | ||
| 109 | const u32 target = offset + instr.bra.GetBranchTarget(); | ||
| 110 | labels.insert(target); | ||
| 111 | // Continue scanning for an exit method. | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | } | ||
| 116 | return exit_method = ExitMethod::AlwaysReturn; | ||
| 117 | } | ||
| 118 | |||
| 119 | BasicBlock ShaderIR::DecodeRange(u32 begin, u32 end) { | ||
| 120 | BasicBlock basic_block; | ||
| 121 | for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) { | ||
| 122 | pc = DecodeInstr(basic_block, pc); | ||
| 123 | } | ||
| 124 | return std::move(basic_block); | ||
| 125 | } | ||
| 126 | |||
| 127 | u32 ShaderIR::DecodeInstr(BasicBlock& bb, u32 pc) { | ||
| 128 | // Ignore sched instructions when generating code. | ||
| 129 | if (IsSchedInstruction(pc, main_offset)) { | ||
| 130 | return pc + 1; | ||
| 131 | } | ||
| 132 | |||
| 133 | const Instruction instr = {program_code[pc]}; | ||
| 134 | const auto opcode = OpCode::Decode(instr); | ||
| 135 | |||
| 136 | // Decoding failure | ||
| 137 | if (!opcode) { | ||
| 138 | UNIMPLEMENTED_MSG("Unhandled instruction: {0:x}", instr.value); | ||
| 139 | return pc + 1; | ||
| 140 | } | ||
| 141 | |||
| 142 | bb.push_back( | ||
| 143 | Comment(fmt::format("{}: {} (0x{:016x})", pc, opcode->get().GetName(), instr.value))); | ||
| 144 | |||
| 145 | using Tegra::Shader::Pred; | ||
| 146 | UNIMPLEMENTED_IF_MSG(instr.pred.full_pred == Pred::NeverExecute, | ||
| 147 | "NeverExecute predicate not implemented"); | ||
| 148 | |||
| 149 | static const std::map<OpCode::Type, u32 (ShaderIR::*)(BasicBlock & code, u32 pc)> decoders = { | ||
| 150 | {OpCode::Type::Arithmetic, &ShaderIR::DecodeArithmetic}, | ||
| 151 | {OpCode::Type::ArithmeticImmediate, &ShaderIR::DecodeArithmeticImmediate}, | ||
| 152 | {OpCode::Type::Bfe, &ShaderIR::DecodeBfe}, | ||
| 153 | {OpCode::Type::Bfi, &ShaderIR::DecodeBfi}, | ||
| 154 | {OpCode::Type::Shift, &ShaderIR::DecodeShift}, | ||
| 155 | {OpCode::Type::ArithmeticInteger, &ShaderIR::DecodeArithmeticInteger}, | ||
| 156 | {OpCode::Type::ArithmeticIntegerImmediate, &ShaderIR::DecodeArithmeticIntegerImmediate}, | ||
| 157 | {OpCode::Type::ArithmeticHalf, &ShaderIR::DecodeArithmeticHalf}, | ||
| 158 | {OpCode::Type::ArithmeticHalfImmediate, &ShaderIR::DecodeArithmeticHalfImmediate}, | ||
| 159 | {OpCode::Type::Ffma, &ShaderIR::DecodeFfma}, | ||
| 160 | {OpCode::Type::Hfma2, &ShaderIR::DecodeHfma2}, | ||
| 161 | {OpCode::Type::Conversion, &ShaderIR::DecodeConversion}, | ||
| 162 | {OpCode::Type::Memory, &ShaderIR::DecodeMemory}, | ||
| 163 | {OpCode::Type::FloatSetPredicate, &ShaderIR::DecodeFloatSetPredicate}, | ||
| 164 | {OpCode::Type::IntegerSetPredicate, &ShaderIR::DecodeIntegerSetPredicate}, | ||
| 165 | {OpCode::Type::HalfSetPredicate, &ShaderIR::DecodeHalfSetPredicate}, | ||
| 166 | {OpCode::Type::PredicateSetRegister, &ShaderIR::DecodePredicateSetRegister}, | ||
| 167 | {OpCode::Type::PredicateSetPredicate, &ShaderIR::DecodePredicateSetPredicate}, | ||
| 168 | {OpCode::Type::RegisterSetPredicate, &ShaderIR::DecodeRegisterSetPredicate}, | ||
| 169 | {OpCode::Type::FloatSet, &ShaderIR::DecodeFloatSet}, | ||
| 170 | {OpCode::Type::IntegerSet, &ShaderIR::DecodeIntegerSet}, | ||
| 171 | {OpCode::Type::HalfSet, &ShaderIR::DecodeHalfSet}, | ||
| 172 | {OpCode::Type::Xmad, &ShaderIR::DecodeXmad}, | ||
| 173 | }; | ||
| 174 | |||
| 175 | std::vector<Node> code; | ||
| 176 | if (const auto decoder = decoders.find(opcode->get().GetType()); decoder != decoders.end()) { | ||
| 177 | pc = (this->*decoder->second)(code, pc); | ||
| 178 | } else { | ||
| 179 | pc = DecodeOther(code, pc); | ||
| 180 | } | ||
| 181 | |||
| 182 | // Some instructions (like SSY) don't have a predicate field, they are always unconditionally | ||
| 183 | // executed. | ||
| 184 | const bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->get().GetId()); | ||
| 185 | const auto pred_index = static_cast<u32>(instr.pred.pred_index); | ||
| 186 | |||
| 187 | if (can_be_predicated && pred_index != static_cast<u32>(Pred::UnusedIndex)) { | ||
| 188 | bb.push_back( | ||
| 189 | Conditional(GetPredicate(pred_index, instr.negate_pred != 0), std::move(code))); | ||
| 190 | } else { | ||
| 191 | for (auto& node : code) { | ||
| 192 | bb.push_back(std::move(node)); | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | return pc + 1; | ||
| 197 | } | ||
| 198 | |||
| 199 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp new file mode 100644 index 000000000..9242a7389 --- /dev/null +++ b/src/video_core/shader/decode/arithmetic.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/arithmetic_half.cpp b/src/video_core/shader/decode/arithmetic_half.cpp new file mode 100644 index 000000000..3b189b0d1 --- /dev/null +++ b/src/video_core/shader/decode/arithmetic_half.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeArithmeticHalf(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp new file mode 100644 index 000000000..8d8a2dad9 --- /dev/null +++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeArithmeticHalfImmediate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/arithmetic_immediate.cpp b/src/video_core/shader/decode/arithmetic_immediate.cpp new file mode 100644 index 000000000..18fd2082e --- /dev/null +++ b/src/video_core/shader/decode/arithmetic_immediate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeArithmeticImmediate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp new file mode 100644 index 000000000..12c64e97a --- /dev/null +++ b/src/video_core/shader/decode/arithmetic_integer.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp new file mode 100644 index 000000000..46f340235 --- /dev/null +++ b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeArithmeticIntegerImmediate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/bfe.cpp b/src/video_core/shader/decode/bfe.cpp new file mode 100644 index 000000000..ffd904c54 --- /dev/null +++ b/src/video_core/shader/decode/bfe.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeBfe(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/bfi.cpp b/src/video_core/shader/decode/bfi.cpp new file mode 100644 index 000000000..b94d46ce6 --- /dev/null +++ b/src/video_core/shader/decode/bfi.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeBfi(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/conversion.cpp b/src/video_core/shader/decode/conversion.cpp new file mode 100644 index 000000000..c6eb2952c --- /dev/null +++ b/src/video_core/shader/decode/conversion.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeConversion(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/decode_integer_set.cpp b/src/video_core/shader/decode/decode_integer_set.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/video_core/shader/decode/decode_integer_set.cpp | |||
diff --git a/src/video_core/shader/decode/ffma.cpp b/src/video_core/shader/decode/ffma.cpp new file mode 100644 index 000000000..2044113f0 --- /dev/null +++ b/src/video_core/shader/decode/ffma.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeFfma(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/float_set.cpp b/src/video_core/shader/decode/float_set.cpp new file mode 100644 index 000000000..17d47c17a --- /dev/null +++ b/src/video_core/shader/decode/float_set.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeFloatSet(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/float_set_predicate.cpp b/src/video_core/shader/decode/float_set_predicate.cpp new file mode 100644 index 000000000..1dbe34353 --- /dev/null +++ b/src/video_core/shader/decode/float_set_predicate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeFloatSetPredicate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp new file mode 100644 index 000000000..af363d5d2 --- /dev/null +++ b/src/video_core/shader/decode/half_set.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeHalfSet(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp new file mode 100644 index 000000000..5fe123ea5 --- /dev/null +++ b/src/video_core/shader/decode/half_set_predicate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeHalfSetPredicate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/hfma2.cpp b/src/video_core/shader/decode/hfma2.cpp new file mode 100644 index 000000000..5ce08481e --- /dev/null +++ b/src/video_core/shader/decode/hfma2.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeHfma2(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/integer_set.cpp b/src/video_core/shader/decode/integer_set.cpp new file mode 100644 index 000000000..316a7d8ad --- /dev/null +++ b/src/video_core/shader/decode/integer_set.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeIntegerSet(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/integer_set_predicate.cpp b/src/video_core/shader/decode/integer_set_predicate.cpp new file mode 100644 index 000000000..10975c394 --- /dev/null +++ b/src/video_core/shader/decode/integer_set_predicate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeIntegerSetPredicate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp new file mode 100644 index 000000000..d6086004b --- /dev/null +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp new file mode 100644 index 000000000..d84702a4f --- /dev/null +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeOther(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/predicate_set_predicate.cpp b/src/video_core/shader/decode/predicate_set_predicate.cpp new file mode 100644 index 000000000..1ad853fda --- /dev/null +++ b/src/video_core/shader/decode/predicate_set_predicate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodePredicateSetPredicate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/predicate_set_register.cpp b/src/video_core/shader/decode/predicate_set_register.cpp new file mode 100644 index 000000000..67a06b5b4 --- /dev/null +++ b/src/video_core/shader/decode/predicate_set_register.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodePredicateSetRegister(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/register_set_predicate.cpp b/src/video_core/shader/decode/register_set_predicate.cpp new file mode 100644 index 000000000..29a348cf5 --- /dev/null +++ b/src/video_core/shader/decode/register_set_predicate.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeRegisterSetPredicate(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/shift.cpp b/src/video_core/shader/decode/shift.cpp new file mode 100644 index 000000000..41f5b8cb0 --- /dev/null +++ b/src/video_core/shader/decode/shift.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeShift(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp new file mode 100644 index 000000000..27a2fc05d --- /dev/null +++ b/src/video_core/shader/decode/xmad.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/engines/shader_bytecode.h" | ||
| 8 | #include "video_core/shader/shader_ir.h" | ||
| 9 | |||
| 10 | namespace VideoCommon::Shader { | ||
| 11 | |||
| 12 | using Tegra::Shader::Instruction; | ||
| 13 | using Tegra::Shader::OpCode; | ||
| 14 | |||
| 15 | u32 ShaderIR::DecodeXmad(BasicBlock& bb, u32 pc) { | ||
| 16 | const Instruction instr = {program_code[pc]}; | ||
| 17 | const auto opcode = OpCode::Decode(instr); | ||
| 18 | |||
| 19 | UNIMPLEMENTED(); | ||
| 20 | |||
| 21 | return pc; | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp new file mode 100644 index 000000000..db00c8902 --- /dev/null +++ b/src/video_core/shader/shader_ir.cpp | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | // Copyright 2018 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <cmath> | ||
| 6 | #include <unordered_map> | ||
| 7 | |||
| 8 | #include "common/assert.h" | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "video_core/engines/shader_bytecode.h" | ||
| 11 | #include "video_core/shader/shader_ir.h" | ||
| 12 | |||
| 13 | namespace VideoCommon::Shader { | ||
| 14 | |||
| 15 | using Tegra::Shader::Attribute; | ||
| 16 | using Tegra::Shader::Instruction; | ||
| 17 | using Tegra::Shader::IpaMode; | ||
| 18 | using Tegra::Shader::Pred; | ||
| 19 | using Tegra::Shader::PredCondition; | ||
| 20 | using Tegra::Shader::PredOperation; | ||
| 21 | using Tegra::Shader::Register; | ||
| 22 | |||
| 23 | Node ShaderIR::StoreNode(NodeData&& node_data) { | ||
| 24 | auto store = std::make_unique<NodeData>(node_data); | ||
| 25 | const Node node = store.get(); | ||
| 26 | stored_nodes.push_back(std::move(store)); | ||
| 27 | return node; | ||
| 28 | } | ||
| 29 | |||
| 30 | Node ShaderIR::Conditional(Node condition, std::vector<Node>&& code) { | ||
| 31 | return StoreNode(ConditionalNode(condition, std::move(code))); | ||
| 32 | } | ||
| 33 | |||
| 34 | Node ShaderIR::Comment(const std::string& text) { | ||
| 35 | return StoreNode(CommentNode(text)); | ||
| 36 | } | ||
| 37 | |||
| 38 | Node ShaderIR::GetPredicate(u64 pred_, bool negated) { | ||
| 39 | const auto pred = static_cast<Pred>(pred_); | ||
| 40 | if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) { | ||
| 41 | used_predicates.insert(pred); | ||
| 42 | } | ||
| 43 | |||
| 44 | return StoreNode(PredicateNode(pred, negated)); | ||
| 45 | } | ||
| 46 | |||
| 47 | /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, | ||
| 48 | bool is_signed) { | ||
| 49 | if (is_signed) { | ||
| 50 | return operation_code; | ||
| 51 | } | ||
| 52 | switch (operation_code) { | ||
| 53 | case OperationCode::FCastInteger: | ||
| 54 | return OperationCode::FCastUInteger; | ||
| 55 | case OperationCode::IAdd: | ||
| 56 | return OperationCode::UAdd; | ||
| 57 | case OperationCode::IMul: | ||
| 58 | return OperationCode::UMul; | ||
| 59 | case OperationCode::IDiv: | ||
| 60 | return OperationCode::UDiv; | ||
| 61 | case OperationCode::IMin: | ||
| 62 | return OperationCode::UMin; | ||
| 63 | case OperationCode::IMax: | ||
| 64 | return OperationCode::UMax; | ||
| 65 | case OperationCode::ICastFloat: | ||
| 66 | return OperationCode::UCastFloat; | ||
| 67 | case OperationCode::ICastUnsigned: | ||
| 68 | return OperationCode::UCastSigned; | ||
| 69 | case OperationCode::ILogicalShiftLeft: | ||
| 70 | return OperationCode::ULogicalShiftLeft; | ||
| 71 | case OperationCode::ILogicalShiftRight: | ||
| 72 | return OperationCode::ULogicalShiftRight; | ||
| 73 | case OperationCode::IArithmeticShiftRight: | ||
| 74 | return OperationCode::UArithmeticShiftRight; | ||
| 75 | case OperationCode::IBitwiseAnd: | ||
| 76 | return OperationCode::UBitwiseAnd; | ||
| 77 | case OperationCode::IBitwiseOr: | ||
| 78 | return OperationCode::UBitwiseOr; | ||
| 79 | case OperationCode::IBitwiseXor: | ||
| 80 | return OperationCode::UBitwiseXor; | ||
| 81 | case OperationCode::IBitwiseNot: | ||
| 82 | return OperationCode::UBitwiseNot; | ||
| 83 | case OperationCode::IBitfieldInsert: | ||
| 84 | return OperationCode::UBitfieldInsert; | ||
| 85 | case OperationCode::LogicalILessThan: | ||
| 86 | return OperationCode::LogicalULessThan; | ||
| 87 | case OperationCode::LogicalIEqual: | ||
| 88 | return OperationCode::LogicalUEqual; | ||
| 89 | case OperationCode::LogicalILessEqual: | ||
| 90 | return OperationCode::LogicalULessEqual; | ||
| 91 | case OperationCode::LogicalIGreaterThan: | ||
| 92 | return OperationCode::LogicalUGreaterThan; | ||
| 93 | case OperationCode::LogicalINotEqual: | ||
| 94 | return OperationCode::LogicalUNotEqual; | ||
| 95 | case OperationCode::LogicalIGreaterEqual: | ||
| 96 | return OperationCode::LogicalUGreaterEqual; | ||
| 97 | case OperationCode::INegate: | ||
| 98 | UNREACHABLE_MSG("Can't negate an unsigned integer"); | ||
| 99 | case OperationCode::IAbsolute: | ||
| 100 | UNREACHABLE_MSG("Can't apply absolute to an unsigned integer"); | ||
| 101 | } | ||
| 102 | UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast<u32>(operation_code)); | ||
| 103 | } | ||
| 104 | |||
| 105 | } // namespace VideoCommon::Shader \ No newline at end of file | ||
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h new file mode 100644 index 000000000..300cf1083 --- /dev/null +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -0,0 +1,662 @@ | |||
| 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 <set> | ||
| 9 | #include <string> | ||
| 10 | #include <tuple> | ||
| 11 | #include <variant> | ||
| 12 | #include <vector> | ||
| 13 | |||
| 14 | #include "common/assert.h" | ||
| 15 | #include "common/common_types.h" | ||
| 16 | #include "video_core/engines/maxwell_3d.h" | ||
| 17 | #include "video_core/engines/shader_bytecode.h" | ||
| 18 | #include "video_core/engines/shader_header.h" | ||
| 19 | |||
| 20 | namespace VideoCommon::Shader { | ||
| 21 | |||
| 22 | class OperationNode; | ||
| 23 | class ConditionalNode; | ||
| 24 | class GprNode; | ||
| 25 | class ImmediateNode; | ||
| 26 | class InternalFlagNode; | ||
| 27 | class PredicateNode; | ||
| 28 | class AbufNode; ///< Attribute buffer | ||
| 29 | class CbufNode; ///< Constant buffer | ||
| 30 | class LmemNode; ///< Local memory | ||
| 31 | class GmemNode; ///< Global memory | ||
| 32 | class CommentNode; | ||
| 33 | |||
| 34 | using ProgramCode = std::vector<u64>; | ||
| 35 | |||
| 36 | using NodeData = | ||
| 37 | std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, | ||
| 38 | PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>; | ||
| 39 | using Node = const NodeData*; | ||
| 40 | using BasicBlock = std::vector<Node>; | ||
| 41 | |||
| 42 | constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; | ||
| 43 | |||
| 44 | constexpr u32 RZ = 0xff; | ||
| 45 | |||
| 46 | enum class OperationCode { | ||
| 47 | Assign, /// (float& dest, float src) -> void | ||
| 48 | AssignComposite, /// (MetaComponents, float4 src, float&[4] dst) -> void | ||
| 49 | |||
| 50 | Composite, /// (float[4] values) -> float4 | ||
| 51 | Select, /// (MetaArithmetic, bool pred, float a, float b) -> float | ||
| 52 | |||
| 53 | FAdd, /// (MetaArithmetic, float a, float b) -> float | ||
| 54 | FMul, /// (MetaArithmetic, float a, float b) -> float | ||
| 55 | FDiv, /// (MetaArithmetic, float a, float b) -> float | ||
| 56 | FFma, /// (MetaArithmetic, float a, float b, float c) -> float | ||
| 57 | FNegate, /// (MetaArithmetic, float a) -> float | ||
| 58 | FAbsolute, /// (MetaArithmetic, float a) -> float | ||
| 59 | FClamp, /// (MetaArithmetic, float value, float min, float max) -> float | ||
| 60 | FMin, /// (MetaArithmetic, float a, float b) -> float | ||
| 61 | FMax, /// (MetaArithmetic, float a, float b) -> float | ||
| 62 | FCos, /// (MetaArithmetic, float a) -> float | ||
| 63 | FSin, /// (MetaArithmetic, float a) -> float | ||
| 64 | FExp2, /// (MetaArithmetic, float a) -> float | ||
| 65 | FLog2, /// (MetaArithmetic, float a) -> float | ||
| 66 | FInverseSqrt, /// (MetaArithmetic, float a) -> float | ||
| 67 | FSqrt, /// (MetaArithmetic, float a) -> float | ||
| 68 | FRoundEven, /// (MetaArithmetic, float a) -> float | ||
| 69 | FFloor, /// (MetaArithmetic, float a) -> float | ||
| 70 | FCeil, /// (MetaArithmetic, float a) -> float | ||
| 71 | FTrunc, /// (MetaArithmetic, float a) -> float | ||
| 72 | FCastInteger, /// (MetaArithmetic, int a) -> float | ||
| 73 | FCastUInteger, /// (MetaArithmetic, uint a) -> float | ||
| 74 | |||
| 75 | IAdd, /// (MetaArithmetic, int a, int b) -> int | ||
| 76 | IMul, /// (MetaArithmetic, int a, int b) -> int | ||
| 77 | IDiv, /// (MetaArithmetic, int a, int b) -> int | ||
| 78 | INegate, /// (MetaArithmetic, int a) -> int | ||
| 79 | IAbsolute, /// (MetaArithmetic, int a) -> int | ||
| 80 | IMin, /// (MetaArithmetic, int a, int b) -> int | ||
| 81 | IMax, /// (MetaArithmetic, int a, int b) -> int | ||
| 82 | ICastFloat, /// (MetaArithmetic, float a) -> int | ||
| 83 | ICastUnsigned, /// (MetaArithmetic, uint a) -> int | ||
| 84 | ILogicalShiftLeft, /// (MetaArithmetic, int a, uint b) -> int | ||
| 85 | ILogicalShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 86 | IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int | ||
| 87 | IBitwiseAnd, /// (MetaArithmetic, int a, int b) -> int | ||
| 88 | IBitwiseOr, /// (MetaArithmetic, int a, int b) -> int | ||
| 89 | IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int | ||
| 90 | IBitwiseNot, /// (MetaArithmetic, int a) -> int | ||
| 91 | IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int | ||
| 92 | |||
| 93 | UAdd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 94 | UMul, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 95 | UDiv, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 96 | UMin, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 97 | UMax, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 98 | UCastFloat, /// (MetaArithmetic, float a) -> uint | ||
| 99 | UCastSigned, /// (MetaArithmetic, int a) -> uint | ||
| 100 | ULogicalShiftLeft, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 101 | ULogicalShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 102 | UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 103 | UBitwiseAnd, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 104 | UBitwiseOr, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 105 | UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint | ||
| 106 | UBitwiseNot, /// (MetaArithmetic, uint a) -> int | ||
| 107 | UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint | ||
| 108 | |||
| 109 | HAdd, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 110 | HMul, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 | ||
| 111 | HAbsolute, /// (f16vec2 a) -> f16vec2 | ||
| 112 | HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 | ||
| 113 | HMergeF32, /// (f16vec2 src) -> float | ||
| 114 | HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 115 | HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | ||
| 116 | |||
| 117 | LogicalAssign, /// (bool& dst, bool src) -> void | ||
| 118 | LogicalAnd, /// (bool a, bool b) -> bool | ||
| 119 | LogicalOr, /// (bool a, bool b) -> bool | ||
| 120 | LogicalXor, /// (bool a, bool b) -> bool | ||
| 121 | LogicalNegate, /// (bool a) -> bool | ||
| 122 | |||
| 123 | LogicalFLessThan, /// (float a, float b) -> bool | ||
| 124 | LogicalFEqual, /// (float a, float b) -> bool | ||
| 125 | LogicalFLessEqual, /// (float a, float b) -> bool | ||
| 126 | LogicalFGreaterThan, /// (float a, float b) -> bool | ||
| 127 | LogicalFNotEqual, /// (float a, float b) -> bool | ||
| 128 | LogicalFGreaterEqual, /// (float a, float b) -> bool | ||
| 129 | LogicalFIsNan, /// (float a) -> bool | ||
| 130 | |||
| 131 | LogicalILessThan, /// (int a, int b) -> bool | ||
| 132 | LogicalIEqual, /// (int a, int b) -> bool | ||
| 133 | LogicalILessEqual, /// (int a, int b) -> bool | ||
| 134 | LogicalIGreaterThan, /// (int a, int b) -> bool | ||
| 135 | LogicalINotEqual, /// (int a, int b) -> bool | ||
| 136 | LogicalIGreaterEqual, /// (int a, int b) -> bool | ||
| 137 | |||
| 138 | LogicalULessThan, /// (uint a, uint b) -> bool | ||
| 139 | LogicalUEqual, /// (uint a, uint b) -> bool | ||
| 140 | LogicalULessEqual, /// (uint a, uint b) -> bool | ||
| 141 | LogicalUGreaterThan, /// (uint a, uint b) -> bool | ||
| 142 | LogicalUNotEqual, /// (uint a, uint b) -> bool | ||
| 143 | LogicalUGreaterEqual, /// (uint a, uint b) -> bool | ||
| 144 | |||
| 145 | LogicalHLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool | ||
| 146 | LogicalHEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool | ||
| 147 | LogicalHLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool | ||
| 148 | LogicalHGreaterThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool | ||
| 149 | LogicalHNotEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool | ||
| 150 | LogicalHGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool | ||
| 151 | |||
| 152 | F4Texture, /// (MetaTexture, float[N] coords, float[M] params) -> float4 | ||
| 153 | F4TextureLod, /// (MetaTexture, float[N] coords, float[M] params) -> float4 | ||
| 154 | F4TextureGather, /// (MetaTexture, float[N] coords, float[M] params) -> float4 | ||
| 155 | F4TextureQueryDimensions, /// (MetaTexture, float a) -> float4 | ||
| 156 | F4TextureQueryLod, /// (MetaTexture, float[N] coords) -> float4 | ||
| 157 | |||
| 158 | Ipa, /// (abuf src) -> float | ||
| 159 | |||
| 160 | Bra, /// (uint branch_target) -> void | ||
| 161 | Ssy, /// (uint branch_target) -> void | ||
| 162 | Pbk, /// (uint branch_target) -> void | ||
| 163 | Sync, /// () -> void | ||
| 164 | Brk, /// () -> void | ||
| 165 | Exit, /// () -> void | ||
| 166 | Kil, /// () -> void | ||
| 167 | |||
| 168 | YNegate, /// () -> float | ||
| 169 | |||
| 170 | Amount, | ||
| 171 | }; | ||
| 172 | |||
| 173 | enum class InternalFlag { | ||
| 174 | Zero = 0, | ||
| 175 | Sign = 1, | ||
| 176 | Carry = 2, | ||
| 177 | Overflow = 3, | ||
| 178 | Amount = 4, | ||
| 179 | }; | ||
| 180 | |||
| 181 | /// Describes the behaviour of code path of a given entry point and a return point. | ||
| 182 | enum class ExitMethod { | ||
| 183 | Undetermined, ///< Internal value. Only occur when analyzing JMP loop. | ||
| 184 | AlwaysReturn, ///< All code paths reach the return point. | ||
| 185 | Conditional, ///< Code path reaches the return point or an END instruction conditionally. | ||
| 186 | AlwaysEnd, ///< All code paths reach a END instruction. | ||
| 187 | }; | ||
| 188 | |||
| 189 | class Sampler { | ||
| 190 | public: | ||
| 191 | explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | ||
| 192 | bool is_array, bool is_shadow) | ||
| 193 | : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow} {} | ||
| 194 | |||
| 195 | std::size_t GetOffset() const { | ||
| 196 | return offset; | ||
| 197 | } | ||
| 198 | |||
| 199 | u32 GetIndex() const { | ||
| 200 | return static_cast<u32>(index); | ||
| 201 | } | ||
| 202 | |||
| 203 | Tegra::Shader::TextureType GetType() const { | ||
| 204 | return type; | ||
| 205 | } | ||
| 206 | |||
| 207 | bool IsArray() const { | ||
| 208 | return is_array; | ||
| 209 | } | ||
| 210 | |||
| 211 | bool IsShadow() const { | ||
| 212 | return is_shadow; | ||
| 213 | } | ||
| 214 | |||
| 215 | bool operator<(const Sampler& rhs) const { | ||
| 216 | return std::tie(offset, index, type, is_array, is_shadow) < | ||
| 217 | std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_array, rhs.is_shadow); | ||
| 218 | } | ||
| 219 | |||
| 220 | private: | ||
| 221 | /// Offset in TSC memory from which to read the sampler object, as specified by the sampling | ||
| 222 | /// instruction. | ||
| 223 | std::size_t offset{}; | ||
| 224 | std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. | ||
| 225 | Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) | ||
| 226 | bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. | ||
| 227 | bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. | ||
| 228 | }; | ||
| 229 | |||
| 230 | class ConstBuffer { | ||
| 231 | public: | ||
| 232 | void MarkAsUsed(u64 offset) { | ||
| 233 | max_offset = std::max(max_offset, static_cast<u32>(offset)); | ||
| 234 | } | ||
| 235 | |||
| 236 | void MarkAsUsedIndirect() { | ||
| 237 | is_indirect = true; | ||
| 238 | } | ||
| 239 | |||
| 240 | bool IsIndirect() const { | ||
| 241 | return is_indirect; | ||
| 242 | } | ||
| 243 | |||
| 244 | u32 GetSize() const { | ||
| 245 | return max_offset + 1; | ||
| 246 | } | ||
| 247 | |||
| 248 | private: | ||
| 249 | u32 max_offset{}; | ||
| 250 | bool is_indirect{}; | ||
| 251 | }; | ||
| 252 | |||
| 253 | struct MetaArithmetic { | ||
| 254 | bool precise{}; | ||
| 255 | }; | ||
| 256 | |||
| 257 | struct MetaHalfArithmetic { | ||
| 258 | bool precise{}; | ||
| 259 | std::array<Tegra::Shader::HalfType, 3> types = {Tegra::Shader::HalfType::H0_H1, | ||
| 260 | Tegra::Shader::HalfType::H0_H1, | ||
| 261 | Tegra::Shader::HalfType::H0_H1}; | ||
| 262 | bool and_comparison{}; | ||
| 263 | }; | ||
| 264 | |||
| 265 | struct MetaTexture { | ||
| 266 | const Sampler& sampler; | ||
| 267 | u32 coords_count{}; | ||
| 268 | }; | ||
| 269 | |||
| 270 | struct MetaComponents { | ||
| 271 | std::array<u32, 4> components_map{}; | ||
| 272 | |||
| 273 | u32 GetSourceComponent(u32 dest_index) const { | ||
| 274 | return components_map[dest_index]; | ||
| 275 | } | ||
| 276 | }; | ||
| 277 | |||
| 278 | constexpr MetaArithmetic PRECISE = {true}; | ||
| 279 | constexpr MetaArithmetic NO_PRECISE = {false}; | ||
| 280 | constexpr MetaHalfArithmetic HALF_NO_PRECISE = {false}; | ||
| 281 | |||
| 282 | using Meta = std::variant<MetaArithmetic, MetaHalfArithmetic, MetaTexture, MetaComponents>; | ||
| 283 | |||
| 284 | /// Holds any kind of operation that can be done in the IR | ||
| 285 | class OperationNode final { | ||
| 286 | public: | ||
| 287 | template <typename... T> | ||
| 288 | explicit constexpr OperationNode(OperationCode code) : code{code}, meta{} {} | ||
| 289 | |||
| 290 | template <typename... T> | ||
| 291 | explicit constexpr OperationNode(OperationCode code, Meta&& meta) | ||
| 292 | : code{code}, meta{std::move(meta)} {} | ||
| 293 | |||
| 294 | template <typename... T> | ||
| 295 | explicit constexpr OperationNode(OperationCode code, const T*... operands) | ||
| 296 | : OperationNode(code, {}, operands...) {} | ||
| 297 | |||
| 298 | template <typename... T> | ||
| 299 | explicit constexpr OperationNode(OperationCode code, Meta&& meta, const T*... operands_) | ||
| 300 | : code{code}, meta{std::move(meta)} { | ||
| 301 | |||
| 302 | auto operands_list = {operands_...}; | ||
| 303 | for (auto& operand : operands_list) { | ||
| 304 | operands.push_back(operand); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands) | ||
| 309 | : code{code}, meta{meta}, operands{std::move(operands)} {} | ||
| 310 | |||
| 311 | explicit OperationNode(OperationCode code, std::vector<Node>&& operands) | ||
| 312 | : code{code}, meta{}, operands{std::move(operands)} {} | ||
| 313 | |||
| 314 | OperationCode GetCode() const { | ||
| 315 | return code; | ||
| 316 | } | ||
| 317 | |||
| 318 | const Meta& GetMeta() const { | ||
| 319 | return meta; | ||
| 320 | } | ||
| 321 | |||
| 322 | std::size_t GetOperandsCount() const { | ||
| 323 | return operands.size(); | ||
| 324 | } | ||
| 325 | |||
| 326 | Node operator[](std::size_t operand_index) const { | ||
| 327 | return operands.at(operand_index); | ||
| 328 | } | ||
| 329 | |||
| 330 | private: | ||
| 331 | const OperationCode code; | ||
| 332 | const Meta meta; | ||
| 333 | std::vector<Node> operands; | ||
| 334 | }; | ||
| 335 | |||
| 336 | /// Encloses inside any kind of node that returns a boolean conditionally-executed code | ||
| 337 | class ConditionalNode final { | ||
| 338 | public: | ||
| 339 | explicit ConditionalNode(Node condition, std::vector<Node>&& code) | ||
| 340 | : condition{condition}, code{std::move(code)} {} | ||
| 341 | |||
| 342 | Node GetCondition() const { | ||
| 343 | return condition; | ||
| 344 | } | ||
| 345 | |||
| 346 | const std::vector<Node>& GetCode() const { | ||
| 347 | return code; | ||
| 348 | } | ||
| 349 | |||
| 350 | private: | ||
| 351 | const Node condition; ///< Condition to be satisfied | ||
| 352 | std::vector<Node> code; ///< Code to execute | ||
| 353 | }; | ||
| 354 | |||
| 355 | /// A general purpose register | ||
| 356 | class GprNode final { | ||
| 357 | public: | ||
| 358 | explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {} | ||
| 359 | |||
| 360 | u32 GetIndex() const { | ||
| 361 | return static_cast<u32>(index); | ||
| 362 | } | ||
| 363 | |||
| 364 | private: | ||
| 365 | const Tegra::Shader::Register index; | ||
| 366 | }; | ||
| 367 | |||
| 368 | /// A 32-bits value that represents an immediate value | ||
| 369 | class ImmediateNode final { | ||
| 370 | public: | ||
| 371 | explicit constexpr ImmediateNode(u32 value) : value{value} {} | ||
| 372 | |||
| 373 | u32 GetValue() const { | ||
| 374 | return value; | ||
| 375 | } | ||
| 376 | |||
| 377 | private: | ||
| 378 | const u32 value; | ||
| 379 | }; | ||
| 380 | |||
| 381 | /// One of Maxwell's internal flags | ||
| 382 | class InternalFlagNode final { | ||
| 383 | public: | ||
| 384 | explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {} | ||
| 385 | |||
| 386 | InternalFlag GetFlag() const { | ||
| 387 | return flag; | ||
| 388 | } | ||
| 389 | |||
| 390 | private: | ||
| 391 | const InternalFlag flag; | ||
| 392 | }; | ||
| 393 | |||
| 394 | /// A predicate register, it can be negated without aditional nodes | ||
| 395 | class PredicateNode final { | ||
| 396 | public: | ||
| 397 | explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated) | ||
| 398 | : index{index}, negated{negated} {} | ||
| 399 | |||
| 400 | Tegra::Shader::Pred GetIndex() const { | ||
| 401 | return index; | ||
| 402 | } | ||
| 403 | |||
| 404 | bool IsNegated() const { | ||
| 405 | return negated; | ||
| 406 | } | ||
| 407 | |||
| 408 | private: | ||
| 409 | const Tegra::Shader::Pred index; | ||
| 410 | const bool negated; | ||
| 411 | }; | ||
| 412 | |||
| 413 | /// Attribute buffer memory (known as attributes or varyings in GLSL terms) | ||
| 414 | class AbufNode final { | ||
| 415 | public: | ||
| 416 | explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, | ||
| 417 | const Tegra::Shader::IpaMode& input_mode, Node buffer = {}) | ||
| 418 | : input_mode{input_mode}, index{index}, element{element}, buffer{buffer} {} | ||
| 419 | |||
| 420 | explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, | ||
| 421 | Node buffer = {}) | ||
| 422 | : input_mode{}, index{index}, element{element}, buffer{buffer} {} | ||
| 423 | |||
| 424 | Tegra::Shader::IpaMode GetInputMode() const { | ||
| 425 | return input_mode; | ||
| 426 | } | ||
| 427 | |||
| 428 | Tegra::Shader::Attribute::Index GetIndex() const { | ||
| 429 | return index; | ||
| 430 | } | ||
| 431 | |||
| 432 | u32 GetElement() const { | ||
| 433 | return element; | ||
| 434 | } | ||
| 435 | |||
| 436 | Node GetBuffer() const { | ||
| 437 | return buffer; | ||
| 438 | } | ||
| 439 | |||
| 440 | private: | ||
| 441 | const Tegra::Shader::IpaMode input_mode; | ||
| 442 | const Node buffer; | ||
| 443 | const Tegra::Shader::Attribute::Index index; | ||
| 444 | const u32 element; | ||
| 445 | }; | ||
| 446 | |||
| 447 | /// Constant buffer node, usually mapped to uniform buffers in GLSL | ||
| 448 | class CbufNode final { | ||
| 449 | public: | ||
| 450 | explicit constexpr CbufNode(u32 index, Node offset) : index{index}, offset{offset} {} | ||
| 451 | |||
| 452 | u32 GetIndex() const { | ||
| 453 | return index; | ||
| 454 | } | ||
| 455 | |||
| 456 | Node GetOffset() const { | ||
| 457 | return offset; | ||
| 458 | } | ||
| 459 | |||
| 460 | private: | ||
| 461 | const u32 index; | ||
| 462 | const Node offset; | ||
| 463 | }; | ||
| 464 | |||
| 465 | /// Local memory node | ||
| 466 | class LmemNode final { | ||
| 467 | public: | ||
| 468 | explicit constexpr LmemNode(Node address) : address{address} {} | ||
| 469 | |||
| 470 | Node GetAddress() const { | ||
| 471 | return address; | ||
| 472 | } | ||
| 473 | |||
| 474 | private: | ||
| 475 | const Node address; | ||
| 476 | }; | ||
| 477 | |||
| 478 | /// Global memory node | ||
| 479 | class GmemNode final { | ||
| 480 | public: | ||
| 481 | explicit GmemNode(Node address) : address{address} {} | ||
| 482 | |||
| 483 | Node GetAddress() const { | ||
| 484 | return address; | ||
| 485 | } | ||
| 486 | |||
| 487 | private: | ||
| 488 | const Node address; | ||
| 489 | }; | ||
| 490 | |||
| 491 | /// Commentary, can be dropped | ||
| 492 | class CommentNode final { | ||
| 493 | public: | ||
| 494 | explicit CommentNode(const std::string& text) : text{text} {} | ||
| 495 | |||
| 496 | const std::string& GetText() const { | ||
| 497 | return text; | ||
| 498 | } | ||
| 499 | |||
| 500 | private: | ||
| 501 | const std::string text; | ||
| 502 | }; | ||
| 503 | |||
| 504 | class ShaderIR final { | ||
| 505 | public: | ||
| 506 | explicit ShaderIR(const ProgramCode& program_code, u32 main_offset) | ||
| 507 | : program_code{program_code}, main_offset{main_offset} { | ||
| 508 | |||
| 509 | Decode(); | ||
| 510 | } | ||
| 511 | |||
| 512 | const std::map<u32, BasicBlock>& GetBasicBlocks() const { | ||
| 513 | return basic_blocks; | ||
| 514 | } | ||
| 515 | |||
| 516 | const std::set<u32>& GetRegisters() const { | ||
| 517 | return used_registers; | ||
| 518 | } | ||
| 519 | |||
| 520 | const std::set<Tegra::Shader::Pred>& GetPredicates() const { | ||
| 521 | return used_predicates; | ||
| 522 | } | ||
| 523 | |||
| 524 | const std::map<Tegra::Shader::Attribute::Index, std::set<Tegra::Shader::IpaMode>>& | ||
| 525 | GetInputAttributes() const { | ||
| 526 | return used_input_attributes; | ||
| 527 | } | ||
| 528 | |||
| 529 | const std::set<Tegra::Shader::Attribute::Index>& GetOutputAttributes() const { | ||
| 530 | return used_output_attributes; | ||
| 531 | } | ||
| 532 | |||
| 533 | const std::map<u32, ConstBuffer>& GetConstantBuffers() const { | ||
| 534 | return used_cbufs; | ||
| 535 | } | ||
| 536 | |||
| 537 | const std::set<Sampler>& GetSamplers() const { | ||
| 538 | return used_samplers; | ||
| 539 | } | ||
| 540 | |||
| 541 | const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& GetClipDistances() | ||
| 542 | const { | ||
| 543 | return used_clip_distances; | ||
| 544 | } | ||
| 545 | |||
| 546 | std::size_t GetLength() const { | ||
| 547 | return static_cast<std::size_t>(coverage_end * sizeof(u64)); | ||
| 548 | } | ||
| 549 | |||
| 550 | const Tegra::Shader::Header& GetHeader() const { | ||
| 551 | return header; | ||
| 552 | } | ||
| 553 | |||
| 554 | private: | ||
| 555 | void Decode(); | ||
| 556 | |||
| 557 | ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels); | ||
| 558 | |||
| 559 | BasicBlock DecodeRange(u32 begin, u32 end); | ||
| 560 | |||
| 561 | /** | ||
| 562 | * Decodes a single instruction from Tegra to IR. | ||
| 563 | * @param bb Basic block where the nodes will be written to. | ||
| 564 | * @param pc Program counter. Offset to decode. | ||
| 565 | * @return Next address to decode. | ||
| 566 | */ | ||
| 567 | u32 DecodeInstr(BasicBlock& bb, u32 pc); | ||
| 568 | |||
| 569 | u32 DecodeArithmetic(BasicBlock& bb, u32 pc); | ||
| 570 | u32 DecodeArithmeticImmediate(BasicBlock& bb, u32 pc); | ||
| 571 | u32 DecodeBfe(BasicBlock& bb, u32 pc); | ||
| 572 | u32 DecodeBfi(BasicBlock& bb, u32 pc); | ||
| 573 | u32 DecodeShift(BasicBlock& bb, u32 pc); | ||
| 574 | u32 DecodeArithmeticInteger(BasicBlock& bb, u32 pc); | ||
| 575 | u32 DecodeArithmeticIntegerImmediate(BasicBlock& bb, u32 pc); | ||
| 576 | u32 DecodeArithmeticHalf(BasicBlock& bb, u32 pc); | ||
| 577 | u32 DecodeArithmeticHalfImmediate(BasicBlock& bb, u32 pc); | ||
| 578 | u32 DecodeFfma(BasicBlock& bb, u32 pc); | ||
| 579 | u32 DecodeHfma2(BasicBlock& bb, u32 pc); | ||
| 580 | u32 DecodeConversion(BasicBlock& bb, u32 pc); | ||
| 581 | u32 DecodeMemory(BasicBlock& bb, u32 pc); | ||
| 582 | u32 DecodeFloatSetPredicate(BasicBlock& bb, u32 pc); | ||
| 583 | u32 DecodeIntegerSetPredicate(BasicBlock& bb, u32 pc); | ||
| 584 | u32 DecodeHalfSetPredicate(BasicBlock& bb, u32 pc); | ||
| 585 | u32 DecodePredicateSetRegister(BasicBlock& bb, u32 pc); | ||
| 586 | u32 DecodePredicateSetPredicate(BasicBlock& bb, u32 pc); | ||
| 587 | u32 DecodeRegisterSetPredicate(BasicBlock& bb, u32 pc); | ||
| 588 | u32 DecodeFloatSet(BasicBlock& bb, u32 pc); | ||
| 589 | u32 DecodeIntegerSet(BasicBlock& bb, u32 pc); | ||
| 590 | u32 DecodeHalfSet(BasicBlock& bb, u32 pc); | ||
| 591 | u32 DecodeXmad(BasicBlock& bb, u32 pc); | ||
| 592 | u32 DecodeOther(BasicBlock& bb, u32 pc); | ||
| 593 | |||
| 594 | /// Internalizes node's data and returns a managed pointer to a clone of that node | ||
| 595 | Node StoreNode(NodeData&& node_data); | ||
| 596 | |||
| 597 | /// Creates a conditional node | ||
| 598 | Node Conditional(Node condition, std::vector<Node>&& code); | ||
| 599 | /// Creates a commentary | ||
| 600 | Node Comment(const std::string& text); | ||
| 601 | |||
| 602 | /// Generates a node for a passed predicate. It can be optionally negated | ||
| 603 | Node GetPredicate(u64 pred, bool negated = false); | ||
| 604 | |||
| 605 | template <typename... T> | ||
| 606 | inline Node Operation(OperationCode code, const T*... operands) { | ||
| 607 | return StoreNode(OperationNode(code, operands...)); | ||
| 608 | } | ||
| 609 | |||
| 610 | template <typename... T> | ||
| 611 | inline Node Operation(OperationCode code, Meta&& meta, const T*... operands) { | ||
| 612 | return StoreNode(OperationNode(code, std::move(meta), operands...)); | ||
| 613 | } | ||
| 614 | |||
| 615 | template <typename... T> | ||
| 616 | inline Node Operation(OperationCode code, std::vector<Node>&& operands) { | ||
| 617 | return StoreNode(OperationNode(code, std::move(operands))); | ||
| 618 | } | ||
| 619 | |||
| 620 | template <typename... T> | ||
| 621 | inline Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) { | ||
| 622 | return StoreNode(OperationNode(code, std::move(meta), std::move(operands))); | ||
| 623 | } | ||
| 624 | |||
| 625 | template <typename... T> | ||
| 626 | inline Node SignedOperation(OperationCode code, bool is_signed, const T*... operands) { | ||
| 627 | return StoreNode(OperationNode(SignedToUnsignedCode(code, is_signed), operands...)); | ||
| 628 | } | ||
| 629 | |||
| 630 | template <typename... T> | ||
| 631 | inline Node SignedOperation(OperationCode code, bool is_signed, Meta&& meta, | ||
| 632 | const T*... operands) { | ||
| 633 | return StoreNode( | ||
| 634 | OperationNode(SignedToUnsignedCode(code, is_signed), std::move(meta), operands...)); | ||
| 635 | } | ||
| 636 | |||
| 637 | static OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed); | ||
| 638 | |||
| 639 | const ProgramCode& program_code; | ||
| 640 | const u32 main_offset; | ||
| 641 | |||
| 642 | u32 coverage_begin{}; | ||
| 643 | u32 coverage_end{}; | ||
| 644 | std::map<std::pair<u32, u32>, ExitMethod> exit_method_map; | ||
| 645 | |||
| 646 | std::map<u32, BasicBlock> basic_blocks; | ||
| 647 | |||
| 648 | std::vector<std::unique_ptr<NodeData>> stored_nodes; | ||
| 649 | |||
| 650 | std::set<u32> used_registers; | ||
| 651 | std::set<Tegra::Shader::Pred> used_predicates; | ||
| 652 | std::map<Tegra::Shader::Attribute::Index, std::set<Tegra::Shader::IpaMode>> | ||
| 653 | used_input_attributes; | ||
| 654 | std::set<Tegra::Shader::Attribute::Index> used_output_attributes; | ||
| 655 | std::map<u32, ConstBuffer> used_cbufs; | ||
| 656 | std::set<Sampler> used_samplers; | ||
| 657 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | ||
| 658 | |||
| 659 | Tegra::Shader::Header header; | ||
| 660 | }; | ||
| 661 | |||
| 662 | } // namespace VideoCommon::Shader \ No newline at end of file | ||