mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	shader_ir: Initial implementation
This commit is contained in:
		
							parent
							
								
									294df41b86
								
							
						
					
					
						commit
						15a0e1481d
					
				| @ -59,6 +59,33 @@ add_library(video_core STATIC | ||||
|     renderer_opengl/renderer_opengl.h | ||||
|     renderer_opengl/utils.cpp | ||||
|     renderer_opengl/utils.h | ||||
|     shader/decode/arithmetic.cpp | ||||
|     shader/decode/arithmetic_immediate.cpp | ||||
|     shader/decode/bfe.cpp | ||||
|     shader/decode/bfi.cpp | ||||
|     shader/decode/shift.cpp | ||||
|     shader/decode/arithmetic_integer.cpp | ||||
|     shader/decode/arithmetic_integer_immediate.cpp | ||||
|     shader/decode/arithmetic_half.cpp | ||||
|     shader/decode/arithmetic_half_immediate.cpp | ||||
|     shader/decode/ffma.cpp | ||||
|     shader/decode/hfma2.cpp | ||||
|     shader/decode/conversion.cpp | ||||
|     shader/decode/memory.cpp | ||||
|     shader/decode/float_set_predicate.cpp | ||||
|     shader/decode/integer_set_predicate.cpp | ||||
|     shader/decode/half_set_predicate.cpp | ||||
|     shader/decode/predicate_set_register.cpp | ||||
|     shader/decode/predicate_set_predicate.cpp | ||||
|     shader/decode/register_set_predicate.cpp | ||||
|     shader/decode/float_set.cpp | ||||
|     shader/decode/integer_set.cpp | ||||
|     shader/decode/half_set.cpp | ||||
|     shader/decode/xmad.cpp | ||||
|     shader/decode/other.cpp | ||||
|     shader/decode.cpp | ||||
|     shader/shader_ir.cpp | ||||
|     shader/shader_ir.h | ||||
|     surface.cpp | ||||
|     surface.h | ||||
|     textures/astc.cpp | ||||
|  | ||||
| @ -397,6 +397,10 @@ struct IpaMode { | ||||
|     bool operator!=(const IpaMode& a) const { | ||||
|         return !operator==(a); | ||||
|     } | ||||
|     bool operator<(const IpaMode& a) const { | ||||
|         return std::tie(interpolation_mode, sampling_mode) < | ||||
|                std::tie(a.interpolation_mode, a.sampling_mode); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| enum class SystemVariable : u64 { | ||||
|  | ||||
							
								
								
									
										199
									
								
								src/video_core/shader/decode.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/video_core/shader/decode.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cstring> | ||||
| #include <set> | ||||
| 
 | ||||
| #include <fmt/format.h> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/engines/shader_header.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| /// Merges exit method of two parallel branches.
 | ||||
| constexpr ExitMethod ParallelExit(ExitMethod a, ExitMethod b) { | ||||
|     if (a == ExitMethod::Undetermined) { | ||||
|         return b; | ||||
|     } | ||||
|     if (b == ExitMethod::Undetermined) { | ||||
|         return a; | ||||
|     } | ||||
|     if (a == b) { | ||||
|         return a; | ||||
|     } | ||||
|     return ExitMethod::Conditional; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns whether the instruction at the specified offset is a 'sched' instruction. | ||||
|  * Sched instructions always appear before a sequence of 3 instructions. | ||||
|  */ | ||||
| constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) { | ||||
|     constexpr u32 SchedPeriod = 4; | ||||
|     u32 absolute_offset = offset - main_offset; | ||||
| 
 | ||||
|     return (absolute_offset % SchedPeriod) == 0; | ||||
| } | ||||
| 
 | ||||
| void ShaderIR::Decode() { | ||||
|     std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); | ||||
| 
 | ||||
|     std::set<u32> labels; | ||||
|     const ExitMethod exit_method = Scan(main_offset, MAX_PROGRAM_LENGTH, labels); | ||||
|     if (exit_method != ExitMethod::AlwaysEnd) { | ||||
|         UNREACHABLE_MSG("Program does not always end"); | ||||
|     } | ||||
| 
 | ||||
|     if (labels.empty()) { | ||||
|         basic_blocks.insert({main_offset, DecodeRange(main_offset, MAX_PROGRAM_LENGTH)}); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     labels.insert(main_offset); | ||||
| 
 | ||||
|     for (const u32 label : labels) { | ||||
|         const auto next_it = labels.lower_bound(label + 1); | ||||
|         const u32 next_label = next_it == labels.end() ? MAX_PROGRAM_LENGTH : *next_it; | ||||
| 
 | ||||
|         basic_blocks.insert({label, DecodeRange(label, next_label)}); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ExitMethod ShaderIR::Scan(u32 begin, u32 end, std::set<u32>& labels) { | ||||
|     const auto [iter, inserted] = | ||||
|         exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined); | ||||
|     ExitMethod& exit_method = iter->second; | ||||
|     if (!inserted) | ||||
|         return exit_method; | ||||
| 
 | ||||
|     for (u32 offset = begin; offset != end && offset != MAX_PROGRAM_LENGTH; ++offset) { | ||||
|         coverage_begin = std::min(coverage_begin, offset); | ||||
|         coverage_end = std::max(coverage_end, offset + 1); | ||||
| 
 | ||||
|         const Instruction instr = {program_code[offset]}; | ||||
|         const auto opcode = OpCode::Decode(instr); | ||||
|         if (!opcode) | ||||
|             continue; | ||||
|         switch (opcode->get().GetId()) { | ||||
|         case OpCode::Id::EXIT: { | ||||
|             // The EXIT instruction can be predicated, which means that the shader can conditionally
 | ||||
|             // end on this instruction. We have to consider the case where the condition is not met
 | ||||
|             // and check the exit method of that other basic block.
 | ||||
|             using Tegra::Shader::Pred; | ||||
|             if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { | ||||
|                 return exit_method = ExitMethod::AlwaysEnd; | ||||
|             } else { | ||||
|                 const ExitMethod not_met = Scan(offset + 1, end, labels); | ||||
|                 return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met); | ||||
|             } | ||||
|         } | ||||
|         case OpCode::Id::BRA: { | ||||
|             const u32 target = offset + instr.bra.GetBranchTarget(); | ||||
|             labels.insert(target); | ||||
|             const ExitMethod no_jmp = Scan(offset + 1, end, labels); | ||||
|             const ExitMethod jmp = Scan(target, end, labels); | ||||
|             return exit_method = ParallelExit(no_jmp, jmp); | ||||
|         } | ||||
|         case OpCode::Id::SSY: | ||||
|         case OpCode::Id::PBK: { | ||||
|             // The SSY and PBK use a similar encoding as the BRA instruction.
 | ||||
|             UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | ||||
|                                  "Constant buffer branching is not supported"); | ||||
|             const u32 target = offset + instr.bra.GetBranchTarget(); | ||||
|             labels.insert(target); | ||||
|             // Continue scanning for an exit method.
 | ||||
|             break; | ||||
|         } | ||||
|         } | ||||
|     } | ||||
|     return exit_method = ExitMethod::AlwaysReturn; | ||||
| } | ||||
| 
 | ||||
| BasicBlock ShaderIR::DecodeRange(u32 begin, u32 end) { | ||||
|     BasicBlock basic_block; | ||||
|     for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) { | ||||
|         pc = DecodeInstr(basic_block, pc); | ||||
|     } | ||||
|     return std::move(basic_block); | ||||
| } | ||||
| 
 | ||||
| u32 ShaderIR::DecodeInstr(BasicBlock& bb, u32 pc) { | ||||
|     // Ignore sched instructions when generating code.
 | ||||
|     if (IsSchedInstruction(pc, main_offset)) { | ||||
|         return pc + 1; | ||||
|     } | ||||
| 
 | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     // Decoding failure
 | ||||
|     if (!opcode) { | ||||
|         UNIMPLEMENTED_MSG("Unhandled instruction: {0:x}", instr.value); | ||||
|         return pc + 1; | ||||
|     } | ||||
| 
 | ||||
|     bb.push_back( | ||||
|         Comment(fmt::format("{}: {} (0x{:016x})", pc, opcode->get().GetName(), instr.value))); | ||||
| 
 | ||||
|     using Tegra::Shader::Pred; | ||||
|     UNIMPLEMENTED_IF_MSG(instr.pred.full_pred == Pred::NeverExecute, | ||||
|                          "NeverExecute predicate not implemented"); | ||||
| 
 | ||||
|     static const std::map<OpCode::Type, u32 (ShaderIR::*)(BasicBlock & code, u32 pc)> decoders = { | ||||
|         {OpCode::Type::Arithmetic, &ShaderIR::DecodeArithmetic}, | ||||
|         {OpCode::Type::ArithmeticImmediate, &ShaderIR::DecodeArithmeticImmediate}, | ||||
|         {OpCode::Type::Bfe, &ShaderIR::DecodeBfe}, | ||||
|         {OpCode::Type::Bfi, &ShaderIR::DecodeBfi}, | ||||
|         {OpCode::Type::Shift, &ShaderIR::DecodeShift}, | ||||
|         {OpCode::Type::ArithmeticInteger, &ShaderIR::DecodeArithmeticInteger}, | ||||
|         {OpCode::Type::ArithmeticIntegerImmediate, &ShaderIR::DecodeArithmeticIntegerImmediate}, | ||||
|         {OpCode::Type::ArithmeticHalf, &ShaderIR::DecodeArithmeticHalf}, | ||||
|         {OpCode::Type::ArithmeticHalfImmediate, &ShaderIR::DecodeArithmeticHalfImmediate}, | ||||
|         {OpCode::Type::Ffma, &ShaderIR::DecodeFfma}, | ||||
|         {OpCode::Type::Hfma2, &ShaderIR::DecodeHfma2}, | ||||
|         {OpCode::Type::Conversion, &ShaderIR::DecodeConversion}, | ||||
|         {OpCode::Type::Memory, &ShaderIR::DecodeMemory}, | ||||
|         {OpCode::Type::FloatSetPredicate, &ShaderIR::DecodeFloatSetPredicate}, | ||||
|         {OpCode::Type::IntegerSetPredicate, &ShaderIR::DecodeIntegerSetPredicate}, | ||||
|         {OpCode::Type::HalfSetPredicate, &ShaderIR::DecodeHalfSetPredicate}, | ||||
|         {OpCode::Type::PredicateSetRegister, &ShaderIR::DecodePredicateSetRegister}, | ||||
|         {OpCode::Type::PredicateSetPredicate, &ShaderIR::DecodePredicateSetPredicate}, | ||||
|         {OpCode::Type::RegisterSetPredicate, &ShaderIR::DecodeRegisterSetPredicate}, | ||||
|         {OpCode::Type::FloatSet, &ShaderIR::DecodeFloatSet}, | ||||
|         {OpCode::Type::IntegerSet, &ShaderIR::DecodeIntegerSet}, | ||||
|         {OpCode::Type::HalfSet, &ShaderIR::DecodeHalfSet}, | ||||
|         {OpCode::Type::Xmad, &ShaderIR::DecodeXmad}, | ||||
|     }; | ||||
| 
 | ||||
|     std::vector<Node> code; | ||||
|     if (const auto decoder = decoders.find(opcode->get().GetType()); decoder != decoders.end()) { | ||||
|         pc = (this->*decoder->second)(code, pc); | ||||
|     } else { | ||||
|         pc = DecodeOther(code, pc); | ||||
|     } | ||||
| 
 | ||||
|     // Some instructions (like SSY) don't have a predicate field, they are always unconditionally
 | ||||
|     // executed.
 | ||||
|     const bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->get().GetId()); | ||||
|     const auto pred_index = static_cast<u32>(instr.pred.pred_index); | ||||
| 
 | ||||
|     if (can_be_predicated && pred_index != static_cast<u32>(Pred::UnusedIndex)) { | ||||
|         bb.push_back( | ||||
|             Conditional(GetPredicate(pred_index, instr.negate_pred != 0), std::move(code))); | ||||
|     } else { | ||||
|         for (auto& node : code) { | ||||
|             bb.push_back(std::move(node)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return pc + 1; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/arithmetic.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/arithmetic.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/arithmetic_half.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/arithmetic_half.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeArithmeticHalf(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/arithmetic_half_immediate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/arithmetic_half_immediate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeArithmeticHalfImmediate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/arithmetic_immediate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/arithmetic_immediate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeArithmeticImmediate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/arithmetic_integer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/arithmetic_integer.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeArithmeticIntegerImmediate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/bfe.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/bfe.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeBfe(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/bfi.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/bfi.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeBfi(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/conversion.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/conversion.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeConversion(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										0
									
								
								src/video_core/shader/decode/decode_integer_set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/video_core/shader/decode/decode_integer_set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										24
									
								
								src/video_core/shader/decode/ffma.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/ffma.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeFfma(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/float_set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/float_set.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeFloatSet(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/float_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/float_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeFloatSetPredicate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/half_set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/half_set.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeHalfSet(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/half_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/half_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeHalfSetPredicate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/hfma2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/hfma2.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeHfma2(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/integer_set.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/integer_set.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeIntegerSet(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/integer_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/integer_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeIntegerSetPredicate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/memory.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/memory.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeMemory(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/other.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/other.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeOther(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/predicate_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/predicate_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodePredicateSetPredicate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/predicate_set_register.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/predicate_set_register.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodePredicateSetRegister(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/register_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/register_set_predicate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeRegisterSetPredicate(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/shift.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/shift.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeShift(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										24
									
								
								src/video_core/shader/decode/xmad.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/shader/decode/xmad.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeXmad(BasicBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     UNIMPLEMENTED(); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										105
									
								
								src/video_core/shader/shader_ir.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/video_core/shader/shader_ir.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cmath> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/shader/shader_ir.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using Tegra::Shader::Attribute; | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::IpaMode; | ||||
| using Tegra::Shader::Pred; | ||||
| using Tegra::Shader::PredCondition; | ||||
| using Tegra::Shader::PredOperation; | ||||
| using Tegra::Shader::Register; | ||||
| 
 | ||||
| Node ShaderIR::StoreNode(NodeData&& node_data) { | ||||
|     auto store = std::make_unique<NodeData>(node_data); | ||||
|     const Node node = store.get(); | ||||
|     stored_nodes.push_back(std::move(store)); | ||||
|     return node; | ||||
| } | ||||
| 
 | ||||
| Node ShaderIR::Conditional(Node condition, std::vector<Node>&& code) { | ||||
|     return StoreNode(ConditionalNode(condition, std::move(code))); | ||||
| } | ||||
| 
 | ||||
| Node ShaderIR::Comment(const std::string& text) { | ||||
|     return StoreNode(CommentNode(text)); | ||||
| } | ||||
| 
 | ||||
| Node ShaderIR::GetPredicate(u64 pred_, bool negated) { | ||||
|     const auto pred = static_cast<Pred>(pred_); | ||||
|     if (pred != Pred::UnusedIndex && pred != Pred::NeverExecute) { | ||||
|         used_predicates.insert(pred); | ||||
|     } | ||||
| 
 | ||||
|     return StoreNode(PredicateNode(pred, negated)); | ||||
| } | ||||
| 
 | ||||
| /*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code, | ||||
|                                                         bool is_signed) { | ||||
|     if (is_signed) { | ||||
|         return operation_code; | ||||
|     } | ||||
|     switch (operation_code) { | ||||
|     case OperationCode::FCastInteger: | ||||
|         return OperationCode::FCastUInteger; | ||||
|     case OperationCode::IAdd: | ||||
|         return OperationCode::UAdd; | ||||
|     case OperationCode::IMul: | ||||
|         return OperationCode::UMul; | ||||
|     case OperationCode::IDiv: | ||||
|         return OperationCode::UDiv; | ||||
|     case OperationCode::IMin: | ||||
|         return OperationCode::UMin; | ||||
|     case OperationCode::IMax: | ||||
|         return OperationCode::UMax; | ||||
|     case OperationCode::ICastFloat: | ||||
|         return OperationCode::UCastFloat; | ||||
|     case OperationCode::ICastUnsigned: | ||||
|         return OperationCode::UCastSigned; | ||||
|     case OperationCode::ILogicalShiftLeft: | ||||
|         return OperationCode::ULogicalShiftLeft; | ||||
|     case OperationCode::ILogicalShiftRight: | ||||
|         return OperationCode::ULogicalShiftRight; | ||||
|     case OperationCode::IArithmeticShiftRight: | ||||
|         return OperationCode::UArithmeticShiftRight; | ||||
|     case OperationCode::IBitwiseAnd: | ||||
|         return OperationCode::UBitwiseAnd; | ||||
|     case OperationCode::IBitwiseOr: | ||||
|         return OperationCode::UBitwiseOr; | ||||
|     case OperationCode::IBitwiseXor: | ||||
|         return OperationCode::UBitwiseXor; | ||||
|     case OperationCode::IBitwiseNot: | ||||
|         return OperationCode::UBitwiseNot; | ||||
|     case OperationCode::IBitfieldInsert: | ||||
|         return OperationCode::UBitfieldInsert; | ||||
|     case OperationCode::LogicalILessThan: | ||||
|         return OperationCode::LogicalULessThan; | ||||
|     case OperationCode::LogicalIEqual: | ||||
|         return OperationCode::LogicalUEqual; | ||||
|     case OperationCode::LogicalILessEqual: | ||||
|         return OperationCode::LogicalULessEqual; | ||||
|     case OperationCode::LogicalIGreaterThan: | ||||
|         return OperationCode::LogicalUGreaterThan; | ||||
|     case OperationCode::LogicalINotEqual: | ||||
|         return OperationCode::LogicalUNotEqual; | ||||
|     case OperationCode::LogicalIGreaterEqual: | ||||
|         return OperationCode::LogicalUGreaterEqual; | ||||
|     case OperationCode::INegate: | ||||
|         UNREACHABLE_MSG("Can't negate an unsigned integer"); | ||||
|     case OperationCode::IAbsolute: | ||||
|         UNREACHABLE_MSG("Can't apply absolute to an unsigned integer"); | ||||
|     } | ||||
|     UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast<u32>(operation_code)); | ||||
| } | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
							
								
								
									
										662
									
								
								src/video_core/shader/shader_ir.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										662
									
								
								src/video_core/shader/shader_ir.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,662 @@ | ||||
| // Copyright 2018 yuzu Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <map> | ||||
| #include <set> | ||||
| #include <string> | ||||
| #include <tuple> | ||||
| #include <variant> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/maxwell_3d.h" | ||||
| #include "video_core/engines/shader_bytecode.h" | ||||
| #include "video_core/engines/shader_header.h" | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| class OperationNode; | ||||
| class ConditionalNode; | ||||
| class GprNode; | ||||
| class ImmediateNode; | ||||
| class InternalFlagNode; | ||||
| class PredicateNode; | ||||
| class AbufNode; ///< Attribute buffer
 | ||||
| class CbufNode; ///< Constant buffer
 | ||||
| class LmemNode; ///< Local memory
 | ||||
| class GmemNode; ///< Global memory
 | ||||
| class CommentNode; | ||||
| 
 | ||||
| using ProgramCode = std::vector<u64>; | ||||
| 
 | ||||
| using NodeData = | ||||
|     std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, | ||||
|                  PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>; | ||||
| using Node = const NodeData*; | ||||
| using BasicBlock = std::vector<Node>; | ||||
| 
 | ||||
| constexpr u32 MAX_PROGRAM_LENGTH = 0x1000; | ||||
| 
 | ||||
| constexpr u32 RZ = 0xff; | ||||
| 
 | ||||
| enum class OperationCode { | ||||
|     Assign,          /// (float& dest, float src) -> void
 | ||||
|     AssignComposite, /// (MetaComponents, float4 src, float&[4] dst) -> void
 | ||||
| 
 | ||||
|     Composite, /// (float[4] values) -> float4
 | ||||
|     Select,    /// (MetaArithmetic, bool pred, float a, float b) -> float
 | ||||
| 
 | ||||
|     FAdd,          /// (MetaArithmetic, float a, float b) -> float
 | ||||
|     FMul,          /// (MetaArithmetic, float a, float b) -> float
 | ||||
|     FDiv,          /// (MetaArithmetic, float a, float b) -> float
 | ||||
|     FFma,          /// (MetaArithmetic, float a, float b, float c) -> float
 | ||||
|     FNegate,       /// (MetaArithmetic, float a) -> float
 | ||||
|     FAbsolute,     /// (MetaArithmetic, float a) -> float
 | ||||
|     FClamp,        /// (MetaArithmetic, float value, float min, float max) -> float
 | ||||
|     FMin,          /// (MetaArithmetic, float a, float b) -> float
 | ||||
|     FMax,          /// (MetaArithmetic, float a, float b) -> float
 | ||||
|     FCos,          /// (MetaArithmetic, float a) -> float
 | ||||
|     FSin,          /// (MetaArithmetic, float a) -> float
 | ||||
|     FExp2,         /// (MetaArithmetic, float a) -> float
 | ||||
|     FLog2,         /// (MetaArithmetic, float a) -> float
 | ||||
|     FInverseSqrt,  /// (MetaArithmetic, float a) -> float
 | ||||
|     FSqrt,         /// (MetaArithmetic, float a) -> float
 | ||||
|     FRoundEven,    /// (MetaArithmetic, float a) -> float
 | ||||
|     FFloor,        /// (MetaArithmetic, float a) -> float
 | ||||
|     FCeil,         /// (MetaArithmetic, float a) -> float
 | ||||
|     FTrunc,        /// (MetaArithmetic, float a) -> float
 | ||||
|     FCastInteger,  /// (MetaArithmetic, int a) -> float
 | ||||
|     FCastUInteger, /// (MetaArithmetic, uint a) -> float
 | ||||
| 
 | ||||
|     IAdd,                  /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     IMul,                  /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     IDiv,                  /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     INegate,               /// (MetaArithmetic, int a) -> int
 | ||||
|     IAbsolute,             /// (MetaArithmetic, int a) -> int
 | ||||
|     IMin,                  /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     IMax,                  /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     ICastFloat,            /// (MetaArithmetic, float a) -> int
 | ||||
|     ICastUnsigned,         /// (MetaArithmetic, uint a) -> int
 | ||||
|     ILogicalShiftLeft,     /// (MetaArithmetic, int a, uint b) -> int
 | ||||
|     ILogicalShiftRight,    /// (MetaArithmetic, int a, uint b) -> int
 | ||||
|     IArithmeticShiftRight, /// (MetaArithmetic, int a, uint b) -> int
 | ||||
|     IBitwiseAnd,           /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     IBitwiseOr,            /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     IBitwiseXor,           /// (MetaArithmetic, int a, int b) -> int
 | ||||
|     IBitwiseNot,           /// (MetaArithmetic, int a) -> int
 | ||||
|     IBitfieldInsert,       /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
 | ||||
| 
 | ||||
|     UAdd,                  /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UMul,                  /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UDiv,                  /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UMin,                  /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UMax,                  /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UCastFloat,            /// (MetaArithmetic, float a) -> uint
 | ||||
|     UCastSigned,           /// (MetaArithmetic, int a) -> uint
 | ||||
|     ULogicalShiftLeft,     /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     ULogicalShiftRight,    /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UArithmeticShiftRight, /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UBitwiseAnd,           /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UBitwiseOr,            /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UBitwiseXor,           /// (MetaArithmetic, uint a, uint b) -> uint
 | ||||
|     UBitwiseNot,           /// (MetaArithmetic, uint a) -> int
 | ||||
|     UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
 | ||||
| 
 | ||||
|     HAdd,      /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
 | ||||
|     HMul,      /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
 | ||||
|     HAbsolute, /// (f16vec2 a) -> f16vec2
 | ||||
|     HNegate,   /// (f16vec2 a, bool first, bool second) -> f16vec2
 | ||||
|     HMergeF32, /// (f16vec2 src) -> float
 | ||||
|     HMergeH0,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
 | ||||
|     HMergeH1,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
 | ||||
| 
 | ||||
|     LogicalAssign, /// (bool& dst, bool src) -> void
 | ||||
|     LogicalAnd,    /// (bool a, bool b) -> bool
 | ||||
|     LogicalOr,     /// (bool a, bool b) -> bool
 | ||||
|     LogicalXor,    /// (bool a, bool b) -> bool
 | ||||
|     LogicalNegate, /// (bool a) -> bool
 | ||||
| 
 | ||||
|     LogicalFLessThan,     /// (float a, float b) -> bool
 | ||||
|     LogicalFEqual,        /// (float a, float b) -> bool
 | ||||
|     LogicalFLessEqual,    /// (float a, float b) -> bool
 | ||||
|     LogicalFGreaterThan,  /// (float a, float b) -> bool
 | ||||
|     LogicalFNotEqual,     /// (float a, float b) -> bool
 | ||||
|     LogicalFGreaterEqual, /// (float a, float b) -> bool
 | ||||
|     LogicalFIsNan,        /// (float a) -> bool
 | ||||
| 
 | ||||
|     LogicalILessThan,     /// (int a, int b) -> bool
 | ||||
|     LogicalIEqual,        /// (int a, int b) -> bool
 | ||||
|     LogicalILessEqual,    /// (int a, int b) -> bool
 | ||||
|     LogicalIGreaterThan,  /// (int a, int b) -> bool
 | ||||
|     LogicalINotEqual,     /// (int a, int b) -> bool
 | ||||
|     LogicalIGreaterEqual, /// (int a, int b) -> bool
 | ||||
| 
 | ||||
|     LogicalULessThan,     /// (uint a, uint b) -> bool
 | ||||
|     LogicalUEqual,        /// (uint a, uint b) -> bool
 | ||||
|     LogicalULessEqual,    /// (uint a, uint b) -> bool
 | ||||
|     LogicalUGreaterThan,  /// (uint a, uint b) -> bool
 | ||||
|     LogicalUNotEqual,     /// (uint a, uint b) -> bool
 | ||||
|     LogicalUGreaterEqual, /// (uint a, uint b) -> bool
 | ||||
| 
 | ||||
|     LogicalHLessThan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
 | ||||
|     LogicalHEqual,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
 | ||||
|     LogicalHLessEqual,    /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
 | ||||
|     LogicalHGreaterThan,  /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
 | ||||
|     LogicalHNotEqual,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
 | ||||
|     LogicalHGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
 | ||||
| 
 | ||||
|     F4Texture,                /// (MetaTexture, float[N] coords, float[M] params) -> float4
 | ||||
|     F4TextureLod,             /// (MetaTexture, float[N] coords, float[M] params) -> float4
 | ||||
|     F4TextureGather,          /// (MetaTexture, float[N] coords, float[M] params) -> float4
 | ||||
|     F4TextureQueryDimensions, /// (MetaTexture, float a) -> float4
 | ||||
|     F4TextureQueryLod,        /// (MetaTexture, float[N] coords) -> float4
 | ||||
| 
 | ||||
|     Ipa, /// (abuf src) -> float
 | ||||
| 
 | ||||
|     Bra,  /// (uint branch_target) -> void
 | ||||
|     Ssy,  /// (uint branch_target) -> void
 | ||||
|     Pbk,  /// (uint branch_target) -> void
 | ||||
|     Sync, /// () -> void
 | ||||
|     Brk,  /// () -> void
 | ||||
|     Exit, /// () -> void
 | ||||
|     Kil,  /// () -> void
 | ||||
| 
 | ||||
|     YNegate, /// () -> float
 | ||||
| 
 | ||||
|     Amount, | ||||
| }; | ||||
| 
 | ||||
| enum class InternalFlag { | ||||
|     Zero = 0, | ||||
|     Sign = 1, | ||||
|     Carry = 2, | ||||
|     Overflow = 3, | ||||
|     Amount = 4, | ||||
| }; | ||||
| 
 | ||||
| /// Describes the behaviour of code path of a given entry point and a return point.
 | ||||
| enum class ExitMethod { | ||||
|     Undetermined, ///< Internal value. Only occur when analyzing JMP loop.
 | ||||
|     AlwaysReturn, ///< All code paths reach the return point.
 | ||||
|     Conditional,  ///< Code path reaches the return point or an END instruction conditionally.
 | ||||
|     AlwaysEnd,    ///< All code paths reach a END instruction.
 | ||||
| }; | ||||
| 
 | ||||
| class Sampler { | ||||
| public: | ||||
|     explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, | ||||
|                      bool is_array, bool is_shadow) | ||||
|         : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow} {} | ||||
| 
 | ||||
|     std::size_t GetOffset() const { | ||||
|         return offset; | ||||
|     } | ||||
| 
 | ||||
|     u32 GetIndex() const { | ||||
|         return static_cast<u32>(index); | ||||
|     } | ||||
| 
 | ||||
|     Tegra::Shader::TextureType GetType() const { | ||||
|         return type; | ||||
|     } | ||||
| 
 | ||||
|     bool IsArray() const { | ||||
|         return is_array; | ||||
|     } | ||||
| 
 | ||||
|     bool IsShadow() const { | ||||
|         return is_shadow; | ||||
|     } | ||||
| 
 | ||||
|     bool operator<(const Sampler& rhs) const { | ||||
|         return std::tie(offset, index, type, is_array, is_shadow) < | ||||
|                std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_array, rhs.is_shadow); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     /// Offset in TSC memory from which to read the sampler object, as specified by the sampling
 | ||||
|     /// instruction.
 | ||||
|     std::size_t offset{}; | ||||
|     std::size_t index{}; ///< Value used to index into the generated GLSL sampler array.
 | ||||
|     Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
 | ||||
|     bool is_array{};  ///< Whether the texture is being sampled as an array texture or not.
 | ||||
|     bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
 | ||||
| }; | ||||
| 
 | ||||
| class ConstBuffer { | ||||
| public: | ||||
|     void MarkAsUsed(u64 offset) { | ||||
|         max_offset = std::max(max_offset, static_cast<u32>(offset)); | ||||
|     } | ||||
| 
 | ||||
|     void MarkAsUsedIndirect() { | ||||
|         is_indirect = true; | ||||
|     } | ||||
| 
 | ||||
|     bool IsIndirect() const { | ||||
|         return is_indirect; | ||||
|     } | ||||
| 
 | ||||
|     u32 GetSize() const { | ||||
|         return max_offset + 1; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     u32 max_offset{}; | ||||
|     bool is_indirect{}; | ||||
| }; | ||||
| 
 | ||||
| struct MetaArithmetic { | ||||
|     bool precise{}; | ||||
| }; | ||||
| 
 | ||||
| struct MetaHalfArithmetic { | ||||
|     bool precise{}; | ||||
|     std::array<Tegra::Shader::HalfType, 3> types = {Tegra::Shader::HalfType::H0_H1, | ||||
|                                                     Tegra::Shader::HalfType::H0_H1, | ||||
|                                                     Tegra::Shader::HalfType::H0_H1}; | ||||
|     bool and_comparison{}; | ||||
| }; | ||||
| 
 | ||||
| struct MetaTexture { | ||||
|     const Sampler& sampler; | ||||
|     u32 coords_count{}; | ||||
| }; | ||||
| 
 | ||||
| struct MetaComponents { | ||||
|     std::array<u32, 4> components_map{}; | ||||
| 
 | ||||
|     u32 GetSourceComponent(u32 dest_index) const { | ||||
|         return components_map[dest_index]; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| constexpr MetaArithmetic PRECISE = {true}; | ||||
| constexpr MetaArithmetic NO_PRECISE = {false}; | ||||
| constexpr MetaHalfArithmetic HALF_NO_PRECISE = {false}; | ||||
| 
 | ||||
| using Meta = std::variant<MetaArithmetic, MetaHalfArithmetic, MetaTexture, MetaComponents>; | ||||
| 
 | ||||
| /// Holds any kind of operation that can be done in the IR
 | ||||
| class OperationNode final { | ||||
| public: | ||||
|     template <typename... T> | ||||
|     explicit constexpr OperationNode(OperationCode code) : code{code}, meta{} {} | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     explicit constexpr OperationNode(OperationCode code, Meta&& meta) | ||||
|         : code{code}, meta{std::move(meta)} {} | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     explicit constexpr OperationNode(OperationCode code, const T*... operands) | ||||
|         : OperationNode(code, {}, operands...) {} | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     explicit constexpr OperationNode(OperationCode code, Meta&& meta, const T*... operands_) | ||||
|         : code{code}, meta{std::move(meta)} { | ||||
| 
 | ||||
|         auto operands_list = {operands_...}; | ||||
|         for (auto& operand : operands_list) { | ||||
|             operands.push_back(operand); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands) | ||||
|         : code{code}, meta{meta}, operands{std::move(operands)} {} | ||||
| 
 | ||||
|     explicit OperationNode(OperationCode code, std::vector<Node>&& operands) | ||||
|         : code{code}, meta{}, operands{std::move(operands)} {} | ||||
| 
 | ||||
|     OperationCode GetCode() const { | ||||
|         return code; | ||||
|     } | ||||
| 
 | ||||
|     const Meta& GetMeta() const { | ||||
|         return meta; | ||||
|     } | ||||
| 
 | ||||
|     std::size_t GetOperandsCount() const { | ||||
|         return operands.size(); | ||||
|     } | ||||
| 
 | ||||
|     Node operator[](std::size_t operand_index) const { | ||||
|         return operands.at(operand_index); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const OperationCode code; | ||||
|     const Meta meta; | ||||
|     std::vector<Node> operands; | ||||
| }; | ||||
| 
 | ||||
| /// Encloses inside any kind of node that returns a boolean conditionally-executed code
 | ||||
| class ConditionalNode final { | ||||
| public: | ||||
|     explicit ConditionalNode(Node condition, std::vector<Node>&& code) | ||||
|         : condition{condition}, code{std::move(code)} {} | ||||
| 
 | ||||
|     Node GetCondition() const { | ||||
|         return condition; | ||||
|     } | ||||
| 
 | ||||
|     const std::vector<Node>& GetCode() const { | ||||
|         return code; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const Node condition;   ///< Condition to be satisfied
 | ||||
|     std::vector<Node> code; ///< Code to execute
 | ||||
| }; | ||||
| 
 | ||||
| /// A general purpose register
 | ||||
| class GprNode final { | ||||
| public: | ||||
|     explicit constexpr GprNode(Tegra::Shader::Register index) : index{index} {} | ||||
| 
 | ||||
|     u32 GetIndex() const { | ||||
|         return static_cast<u32>(index); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const Tegra::Shader::Register index; | ||||
| }; | ||||
| 
 | ||||
| /// A 32-bits value that represents an immediate value
 | ||||
| class ImmediateNode final { | ||||
| public: | ||||
|     explicit constexpr ImmediateNode(u32 value) : value{value} {} | ||||
| 
 | ||||
|     u32 GetValue() const { | ||||
|         return value; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const u32 value; | ||||
| }; | ||||
| 
 | ||||
| /// One of Maxwell's internal flags
 | ||||
| class InternalFlagNode final { | ||||
| public: | ||||
|     explicit constexpr InternalFlagNode(InternalFlag flag) : flag{flag} {} | ||||
| 
 | ||||
|     InternalFlag GetFlag() const { | ||||
|         return flag; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const InternalFlag flag; | ||||
| }; | ||||
| 
 | ||||
| /// A predicate register, it can be negated without aditional nodes
 | ||||
| class PredicateNode final { | ||||
| public: | ||||
|     explicit constexpr PredicateNode(Tegra::Shader::Pred index, bool negated) | ||||
|         : index{index}, negated{negated} {} | ||||
| 
 | ||||
|     Tegra::Shader::Pred GetIndex() const { | ||||
|         return index; | ||||
|     } | ||||
| 
 | ||||
|     bool IsNegated() const { | ||||
|         return negated; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const Tegra::Shader::Pred index; | ||||
|     const bool negated; | ||||
| }; | ||||
| 
 | ||||
| /// Attribute buffer memory (known as attributes or varyings in GLSL terms)
 | ||||
| class AbufNode final { | ||||
| public: | ||||
|     explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, | ||||
|                                 const Tegra::Shader::IpaMode& input_mode, Node buffer = {}) | ||||
|         : input_mode{input_mode}, index{index}, element{element}, buffer{buffer} {} | ||||
| 
 | ||||
|     explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, | ||||
|                                 Node buffer = {}) | ||||
|         : input_mode{}, index{index}, element{element}, buffer{buffer} {} | ||||
| 
 | ||||
|     Tegra::Shader::IpaMode GetInputMode() const { | ||||
|         return input_mode; | ||||
|     } | ||||
| 
 | ||||
|     Tegra::Shader::Attribute::Index GetIndex() const { | ||||
|         return index; | ||||
|     } | ||||
| 
 | ||||
|     u32 GetElement() const { | ||||
|         return element; | ||||
|     } | ||||
| 
 | ||||
|     Node GetBuffer() const { | ||||
|         return buffer; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const Tegra::Shader::IpaMode input_mode; | ||||
|     const Node buffer; | ||||
|     const Tegra::Shader::Attribute::Index index; | ||||
|     const u32 element; | ||||
| }; | ||||
| 
 | ||||
| /// Constant buffer node, usually mapped to uniform buffers in GLSL
 | ||||
| class CbufNode final { | ||||
| public: | ||||
|     explicit constexpr CbufNode(u32 index, Node offset) : index{index}, offset{offset} {} | ||||
| 
 | ||||
|     u32 GetIndex() const { | ||||
|         return index; | ||||
|     } | ||||
| 
 | ||||
|     Node GetOffset() const { | ||||
|         return offset; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const u32 index; | ||||
|     const Node offset; | ||||
| }; | ||||
| 
 | ||||
| /// Local memory node
 | ||||
| class LmemNode final { | ||||
| public: | ||||
|     explicit constexpr LmemNode(Node address) : address{address} {} | ||||
| 
 | ||||
|     Node GetAddress() const { | ||||
|         return address; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const Node address; | ||||
| }; | ||||
| 
 | ||||
| /// Global memory node
 | ||||
| class GmemNode final { | ||||
| public: | ||||
|     explicit GmemNode(Node address) : address{address} {} | ||||
| 
 | ||||
|     Node GetAddress() const { | ||||
|         return address; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const Node address; | ||||
| }; | ||||
| 
 | ||||
| /// Commentary, can be dropped
 | ||||
| class CommentNode final { | ||||
| public: | ||||
|     explicit CommentNode(const std::string& text) : text{text} {} | ||||
| 
 | ||||
|     const std::string& GetText() const { | ||||
|         return text; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const std::string text; | ||||
| }; | ||||
| 
 | ||||
| class ShaderIR final { | ||||
| public: | ||||
|     explicit ShaderIR(const ProgramCode& program_code, u32 main_offset) | ||||
|         : program_code{program_code}, main_offset{main_offset} { | ||||
| 
 | ||||
|         Decode(); | ||||
|     } | ||||
| 
 | ||||
|     const std::map<u32, BasicBlock>& GetBasicBlocks() const { | ||||
|         return basic_blocks; | ||||
|     } | ||||
| 
 | ||||
|     const std::set<u32>& GetRegisters() const { | ||||
|         return used_registers; | ||||
|     } | ||||
| 
 | ||||
|     const std::set<Tegra::Shader::Pred>& GetPredicates() const { | ||||
|         return used_predicates; | ||||
|     } | ||||
| 
 | ||||
|     const std::map<Tegra::Shader::Attribute::Index, std::set<Tegra::Shader::IpaMode>>& | ||||
|     GetInputAttributes() const { | ||||
|         return used_input_attributes; | ||||
|     } | ||||
| 
 | ||||
|     const std::set<Tegra::Shader::Attribute::Index>& GetOutputAttributes() const { | ||||
|         return used_output_attributes; | ||||
|     } | ||||
| 
 | ||||
|     const std::map<u32, ConstBuffer>& GetConstantBuffers() const { | ||||
|         return used_cbufs; | ||||
|     } | ||||
| 
 | ||||
|     const std::set<Sampler>& GetSamplers() const { | ||||
|         return used_samplers; | ||||
|     } | ||||
| 
 | ||||
|     const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& GetClipDistances() | ||||
|         const { | ||||
|         return used_clip_distances; | ||||
|     } | ||||
| 
 | ||||
|     std::size_t GetLength() const { | ||||
|         return static_cast<std::size_t>(coverage_end * sizeof(u64)); | ||||
|     } | ||||
| 
 | ||||
|     const Tegra::Shader::Header& GetHeader() const { | ||||
|         return header; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void Decode(); | ||||
| 
 | ||||
|     ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels); | ||||
| 
 | ||||
|     BasicBlock DecodeRange(u32 begin, u32 end); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Decodes a single instruction from Tegra to IR. | ||||
|      * @param bb Basic block where the nodes will be written to. | ||||
|      * @param pc Program counter. Offset to decode. | ||||
|      * @return Next address to decode. | ||||
|      */ | ||||
|     u32 DecodeInstr(BasicBlock& bb, u32 pc); | ||||
| 
 | ||||
|     u32 DecodeArithmetic(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeArithmeticImmediate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeBfe(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeBfi(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeShift(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeArithmeticInteger(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeArithmeticIntegerImmediate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeArithmeticHalf(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeArithmeticHalfImmediate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeFfma(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeHfma2(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeConversion(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeMemory(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeFloatSetPredicate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeIntegerSetPredicate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeHalfSetPredicate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodePredicateSetRegister(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodePredicateSetPredicate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeRegisterSetPredicate(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeFloatSet(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeIntegerSet(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeHalfSet(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeXmad(BasicBlock& bb, u32 pc); | ||||
|     u32 DecodeOther(BasicBlock& bb, u32 pc); | ||||
| 
 | ||||
|     /// Internalizes node's data and returns a managed pointer to a clone of that node
 | ||||
|     Node StoreNode(NodeData&& node_data); | ||||
| 
 | ||||
|     /// Creates a conditional node
 | ||||
|     Node Conditional(Node condition, std::vector<Node>&& code); | ||||
|     /// Creates a commentary
 | ||||
|     Node Comment(const std::string& text); | ||||
| 
 | ||||
|     /// Generates a node for a passed predicate. It can be optionally negated
 | ||||
|     Node GetPredicate(u64 pred, bool negated = false); | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     inline Node Operation(OperationCode code, const T*... operands) { | ||||
|         return StoreNode(OperationNode(code, operands...)); | ||||
|     } | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     inline Node Operation(OperationCode code, Meta&& meta, const T*... operands) { | ||||
|         return StoreNode(OperationNode(code, std::move(meta), operands...)); | ||||
|     } | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     inline Node Operation(OperationCode code, std::vector<Node>&& operands) { | ||||
|         return StoreNode(OperationNode(code, std::move(operands))); | ||||
|     } | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     inline Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) { | ||||
|         return StoreNode(OperationNode(code, std::move(meta), std::move(operands))); | ||||
|     } | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     inline Node SignedOperation(OperationCode code, bool is_signed, const T*... operands) { | ||||
|         return StoreNode(OperationNode(SignedToUnsignedCode(code, is_signed), operands...)); | ||||
|     } | ||||
| 
 | ||||
|     template <typename... T> | ||||
|     inline Node SignedOperation(OperationCode code, bool is_signed, Meta&& meta, | ||||
|                                 const T*... operands) { | ||||
|         return StoreNode( | ||||
|             OperationNode(SignedToUnsignedCode(code, is_signed), std::move(meta), operands...)); | ||||
|     } | ||||
| 
 | ||||
|     static OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed); | ||||
| 
 | ||||
|     const ProgramCode& program_code; | ||||
|     const u32 main_offset; | ||||
| 
 | ||||
|     u32 coverage_begin{}; | ||||
|     u32 coverage_end{}; | ||||
|     std::map<std::pair<u32, u32>, ExitMethod> exit_method_map; | ||||
| 
 | ||||
|     std::map<u32, BasicBlock> basic_blocks; | ||||
| 
 | ||||
|     std::vector<std::unique_ptr<NodeData>> stored_nodes; | ||||
| 
 | ||||
|     std::set<u32> used_registers; | ||||
|     std::set<Tegra::Shader::Pred> used_predicates; | ||||
|     std::map<Tegra::Shader::Attribute::Index, std::set<Tegra::Shader::IpaMode>> | ||||
|         used_input_attributes; | ||||
|     std::set<Tegra::Shader::Attribute::Index> used_output_attributes; | ||||
|     std::map<u32, ConstBuffer> used_cbufs; | ||||
|     std::set<Sampler> used_samplers; | ||||
|     std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | ||||
| 
 | ||||
|     Tegra::Shader::Header header; | ||||
| }; | ||||
| 
 | ||||
| } // namespace VideoCommon::Shader
 | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
						ReinUsesLisp