mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	ShaderGen: Implemented the fsetp instruction.
Predicate variables are now added to the generated shader code in the form of 'pX' where X is the predicate id. These predicate variables are initialized to false on shader startup and are set via the fsetp instructions. TODO: * Not all the comparison types are implemented. * Only the single-predicate version is implemented.
This commit is contained in:
		
							parent
							
								
									d03fc77475
								
							
						
					
					
						commit
						0a5e01b710
					
				| @ -109,6 +109,8 @@ union OpCode { | |||||||
| 
 | 
 | ||||||
|         FSETP_R = 0x5BB, |         FSETP_R = 0x5BB, | ||||||
|         FSETP_C = 0x4BB, |         FSETP_C = 0x4BB, | ||||||
|  |         FSETP_IMM = 0x36B, | ||||||
|  |         FSETP_NEG_IMM = 0x37B, | ||||||
|         EXIT = 0xE30, |         EXIT = 0xE30, | ||||||
|         KIL = 0xE33, |         KIL = 0xE33, | ||||||
| 
 | 
 | ||||||
| @ -124,6 +126,7 @@ union OpCode { | |||||||
|         Ffma, |         Ffma, | ||||||
|         Flow, |         Flow, | ||||||
|         Memory, |         Memory, | ||||||
|  |         FloatPredicate, | ||||||
|         Unknown, |         Unknown, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
| @ -164,6 +167,9 @@ union OpCode { | |||||||
|         case Id::FSETP_C: |         case Id::FSETP_C: | ||||||
|         case Id::KIL: |         case Id::KIL: | ||||||
|             return op4; |             return op4; | ||||||
|  |         case Id::FSETP_IMM: | ||||||
|  |         case Id::FSETP_NEG_IMM: | ||||||
|  |             return Id::FSETP_IMM; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         switch (op5) { |         switch (op5) { | ||||||
| @ -241,8 +247,9 @@ union OpCode { | |||||||
|         info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"}; |         info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"}; | ||||||
|         info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"}; |         info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"}; | ||||||
|         info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"}; |         info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"}; | ||||||
|         info_table[Id::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; |         info_table[Id::FSETP_C] = {Type::FloatPredicate, "fsetp_c"}; | ||||||
|         info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; |         info_table[Id::FSETP_R] = {Type::FloatPredicate, "fsetp_r"}; | ||||||
|  |         info_table[Id::FSETP_IMM] = {Type::FloatPredicate, "fsetp_imm"}; | ||||||
|         info_table[Id::EXIT] = {Type::Trivial, "exit"}; |         info_table[Id::EXIT] = {Type::Trivial, "exit"}; | ||||||
|         info_table[Id::IPA] = {Type::Trivial, "ipa"}; |         info_table[Id::IPA] = {Type::Trivial, "ipa"}; | ||||||
|         info_table[Id::KIL] = {Type::Flow, "kil"}; |         info_table[Id::KIL] = {Type::Flow, "kil"}; | ||||||
| @ -286,7 +293,23 @@ namespace Shader { | |||||||
| 
 | 
 | ||||||
| enum class Pred : u64 { | enum class Pred : u64 { | ||||||
|     UnusedIndex = 0x7, |     UnusedIndex = 0x7, | ||||||
|     NeverExecute = 0xf, |     NeverExecute = 0xF, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class PredCondition : u64 { | ||||||
|  |     LessThan = 1, | ||||||
|  |     Equal = 2, | ||||||
|  |     LessEqual = 3, | ||||||
|  |     GreaterThan = 4, | ||||||
|  |     NotEqual = 5, | ||||||
|  |     GreaterEqual = 6, | ||||||
|  |     // TODO(Subv): Other condition types
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum class PredOperation : u64 { | ||||||
|  |     And = 0, | ||||||
|  |     Or = 1, | ||||||
|  |     Xor = 2, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class SubOp : u64 { | enum class SubOp : u64 { | ||||||
| @ -346,6 +369,20 @@ union Instruction { | |||||||
|         BitField<49, 1, u64> negate_c; |         BitField<49, 1, u64> negate_c; | ||||||
|     } ffma; |     } ffma; | ||||||
| 
 | 
 | ||||||
|  |     union { | ||||||
|  |         BitField<0, 3, u64> pred0; | ||||||
|  |         BitField<3, 3, u64> pred3; | ||||||
|  |         BitField<7, 1, u64> abs_a; | ||||||
|  |         BitField<39, 3, u64> pred39; | ||||||
|  |         BitField<42, 1, u64> neg_pred; | ||||||
|  |         BitField<43, 1, u64> neg_a; | ||||||
|  |         BitField<44, 1, u64> abs_b; | ||||||
|  |         BitField<45, 2, PredOperation> op; | ||||||
|  |         BitField<47, 1, u64> ftz; | ||||||
|  |         BitField<48, 4, PredCondition> cond; | ||||||
|  |         BitField<56, 1, u64> neg_b; | ||||||
|  |     } fsetp; | ||||||
|  | 
 | ||||||
|     BitField<61, 1, u64> is_b_imm; |     BitField<61, 1, u64> is_b_imm; | ||||||
|     BitField<60, 1, u64> is_b_gpr; |     BitField<60, 1, u64> is_b_gpr; | ||||||
|     BitField<59, 1, u64> is_c_gpr; |     BitField<59, 1, u64> is_c_gpr; | ||||||
|  | |||||||
| @ -278,6 +278,21 @@ private: | |||||||
|         shader.AddLine(dest + " = " + src + ";"); |         shader.AddLine(dest + " = " + src + ";"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /*
 | ||||||
|  |      * Writes code that assigns a predicate boolean variable. | ||||||
|  |      * @param pred The id of the predicate to write to. | ||||||
|  |      * @param value The expression value to assign to the predicate. | ||||||
|  |      */ | ||||||
|  |     void SetPredicate(u64 pred, const std::string& value) { | ||||||
|  |         using Tegra::Shader::Pred; | ||||||
|  |         // Can't assign to the constant predicate.
 | ||||||
|  |         ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); | ||||||
|  | 
 | ||||||
|  |         std::string variable = 'p' + std::to_string(pred); | ||||||
|  |         shader.AddLine(variable + " = " + value + ';'); | ||||||
|  |         declr_predicates.insert(std::move(variable)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /*
 |     /*
 | ||||||
|      * Returns whether the instruction at the specified offset is a 'sched' instruction. |      * Returns whether the instruction at the specified offset is a 'sched' instruction. | ||||||
|      * Sched instructions always appear before a sequence of 3 instructions. |      * Sched instructions always appear before a sequence of 3 instructions. | ||||||
| @ -468,7 +483,57 @@ private: | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |         case OpCode::Type::FloatPredicate: { | ||||||
|  |             std::string op_a = instr.fsetp.neg_a ? "-" : ""; | ||||||
|  |             op_a += GetRegister(instr.gpr8); | ||||||
| 
 | 
 | ||||||
|  |             if (instr.fsetp.abs_a) { | ||||||
|  |                 op_a = "abs(" + op_a + ')'; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             std::string op_b{}; | ||||||
|  | 
 | ||||||
|  |             if (instr.is_b_imm) { | ||||||
|  |                 if (instr.fsetp.neg_b) { | ||||||
|  |                     // Only the immediate version of fsetp has a neg_b bit.
 | ||||||
|  |                     op_b += '-'; | ||||||
|  |                 } | ||||||
|  |                 op_b += '(' + GetImmediate19(instr) + ')'; | ||||||
|  |             } else { | ||||||
|  |                 if (instr.is_b_gpr) { | ||||||
|  |                     op_b += GetRegister(instr.gpr20); | ||||||
|  |                 } else { | ||||||
|  |                     op_b += GetUniform(instr.uniform); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (instr.fsetp.abs_b) { | ||||||
|  |                 op_b = "abs(" + op_b + ')'; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             using Tegra::Shader::Pred; | ||||||
|  |             ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) && | ||||||
|  |                            instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex), | ||||||
|  |                        "Compound predicates are not implemented"); | ||||||
|  | 
 | ||||||
|  |             // We can't use the constant predicate as destination.
 | ||||||
|  |             ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | ||||||
|  | 
 | ||||||
|  |             using Tegra::Shader::PredCondition; | ||||||
|  |             switch (instr.fsetp.cond) { | ||||||
|  |             case PredCondition::LessThan: | ||||||
|  |                 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')'); | ||||||
|  |                 break; | ||||||
|  |             case PredCondition::Equal: | ||||||
|  |                 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')'); | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})", | ||||||
|  |                                static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b); | ||||||
|  |                 UNREACHABLE(); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|         default: { |         default: { | ||||||
|             switch (instr.opcode.EffectiveOpCode()) { |             switch (instr.opcode.EffectiveOpCode()) { | ||||||
|             case OpCode::Id::EXIT: { |             case OpCode::Id::EXIT: { | ||||||
| @ -623,6 +688,12 @@ private: | |||||||
|             declarations.AddNewLine(); |             declarations.AddNewLine(); | ||||||
|             ++const_buffer_layout; |             ++const_buffer_layout; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         declarations.AddNewLine(); | ||||||
|  |         for (const auto& pred : declr_predicates) { | ||||||
|  |             declarations.AddLine("bool " + pred + " = false;"); | ||||||
|  |         } | ||||||
|  |         declarations.AddNewLine(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| @ -636,6 +707,7 @@ private: | |||||||
| 
 | 
 | ||||||
|     // Declarations
 |     // Declarations
 | ||||||
|     std::set<std::string> declr_register; |     std::set<std::string> declr_register; | ||||||
|  |     std::set<std::string> declr_predicates; | ||||||
|     std::set<Attribute::Index> declr_input_attribute; |     std::set<Attribute::Index> declr_input_attribute; | ||||||
|     std::set<Attribute::Index> declr_output_attribute; |     std::set<Attribute::Index> declr_output_attribute; | ||||||
|     std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers; |     std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Subv
						Subv