mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Implemented IPA Properly
This commit is contained in:
		
							parent
							
								
									a1ef02c3e6
								
							
						
					
					
						commit
						e63b229f4a
					
				| @ -76,6 +76,7 @@ union Attribute { | |||||||
|         Position = 7, |         Position = 7, | ||||||
|         Attribute_0 = 8, |         Attribute_0 = 8, | ||||||
|         Attribute_31 = 39, |         Attribute_31 = 39, | ||||||
|  |         PointCoord = 46, | ||||||
|         // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
 |         // This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
 | ||||||
|         // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
 |         // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
 | ||||||
|         // shader.
 |         // shader.
 | ||||||
| @ -246,6 +247,17 @@ enum class TextureType : u64 { | |||||||
| enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; | enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; | ||||||
| enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; | enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; | ||||||
| 
 | 
 | ||||||
|  | struct IpaMode { | ||||||
|  |     IpaInterpMode interpolation_mode; | ||||||
|  |     IpaSampleMode sampling_mode; | ||||||
|  |     inline bool operator==(const IpaMode& a) { | ||||||
|  |         return (a.interpolation_mode == interpolation_mode) && (a.sampling_mode == sampling_mode); | ||||||
|  |     } | ||||||
|  |     inline bool operator!=(const IpaMode& a) { | ||||||
|  |         return !((*this) == a); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| union Instruction { | union Instruction { | ||||||
|     Instruction& operator=(const Instruction& instr) { |     Instruction& operator=(const Instruction& instr) { | ||||||
|         value = instr.value; |         value = instr.value; | ||||||
|  | |||||||
| @ -247,6 +247,7 @@ public: | |||||||
|                         const Maxwell3D::Regs::ShaderStage& stage, const std::string& suffix) |                         const Maxwell3D::Regs::ShaderStage& stage, const std::string& suffix) | ||||||
|         : shader{shader}, declarations{declarations}, stage{stage}, suffix{suffix} { |         : shader{shader}, declarations{declarations}, stage{stage}, suffix{suffix} { | ||||||
|         BuildRegisterList(); |         BuildRegisterList(); | ||||||
|  |         BuildInputList(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
| @ -343,9 +344,10 @@ public: | |||||||
|      * @param elem The element to use for the operation. |      * @param elem The element to use for the operation. | ||||||
|      * @param attribute The input attribute to use as the source value. |      * @param attribute The input attribute to use as the source value. | ||||||
|      */ |      */ | ||||||
|     void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) { |     void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute, | ||||||
|  |                                     const Tegra::Shader::IpaMode& input_mode) { | ||||||
|         std::string dest = GetRegisterAsFloat(reg); |         std::string dest = GetRegisterAsFloat(reg); | ||||||
|         std::string src = GetInputAttribute(attribute) + GetSwizzle(elem); |         std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem); | ||||||
|         shader.AddLine(dest + " = " + src + ';'); |         shader.AddLine(dest + " = " + src + ';'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -412,12 +414,13 @@ public: | |||||||
|         } |         } | ||||||
|         declarations.AddNewLine(); |         declarations.AddNewLine(); | ||||||
| 
 | 
 | ||||||
|         for (const auto& index : declr_input_attribute) { |         for (const auto element : declr_input_attribute) { | ||||||
|             // TODO(bunnei): Use proper number of elements for these
 |             // TODO(bunnei): Use proper number of elements for these
 | ||||||
|             declarations.AddLine("layout(location = " + |             u32 idx = | ||||||
|                                  std::to_string(static_cast<u32>(index) - |                 static_cast<u32>(element.first) - static_cast<u32>(Attribute::Index::Attribute_0); | ||||||
|                                                 static_cast<u32>(Attribute::Index::Attribute_0)) + |             declarations.AddLine("layout(location = " + std::to_string(idx) + ")" + | ||||||
|                                  ") in vec4 " + GetInputAttribute(index) + ';'); |                                  GetInputFlags(element.first) + "in vec4 " + | ||||||
|  |                                  GetInputAttribute(element.first, element.second) + ';'); | ||||||
|         } |         } | ||||||
|         declarations.AddNewLine(); |         declarations.AddNewLine(); | ||||||
| 
 | 
 | ||||||
| @ -532,11 +535,24 @@ private: | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void BuildInputList() { | ||||||
|  |         const u32 size = static_cast<u32>(Attribute::Index::Attribute_31) - | ||||||
|  |                          static_cast<u32>(Attribute::Index::Attribute_0) + 1; | ||||||
|  |         declr_input_attribute.reserve(size); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Generates code representing an input attribute register.
 |     /// Generates code representing an input attribute register.
 | ||||||
|     std::string GetInputAttribute(Attribute::Index attribute) { |     std::string GetInputAttribute(Attribute::Index attribute, | ||||||
|  |                                   const Tegra::Shader::IpaMode& input_mode) { | ||||||
|         switch (attribute) { |         switch (attribute) { | ||||||
|         case Attribute::Index::Position: |         case Attribute::Index::Position: | ||||||
|  |             if (stage != Maxwell3D::Regs::ShaderStage::Fragment) { | ||||||
|                 return "position"; |                 return "position"; | ||||||
|  |             } else { | ||||||
|  |                 return "vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)"; | ||||||
|  |             } | ||||||
|  |         case Attribute::Index::PointCoord: | ||||||
|  |             return "vec4(gl_PointCoord.x, gl_PointCoord.y, 0, 0)"; | ||||||
|         case Attribute::Index::TessCoordInstanceIDVertexID: |         case Attribute::Index::TessCoordInstanceIDVertexID: | ||||||
|             // TODO(Subv): Find out what the values are for the first two elements when inside a
 |             // TODO(Subv): Find out what the values are for the first two elements when inside a
 | ||||||
|             // vertex shader, and what's the value of the fourth element when inside a Tess Eval
 |             // vertex shader, and what's the value of the fourth element when inside a Tess Eval
 | ||||||
| @ -552,7 +568,14 @@ private: | |||||||
|                             static_cast<u32>(Attribute::Index::Attribute_0)}; |                             static_cast<u32>(Attribute::Index::Attribute_0)}; | ||||||
|             if (attribute >= Attribute::Index::Attribute_0 && |             if (attribute >= Attribute::Index::Attribute_0 && | ||||||
|                 attribute <= Attribute::Index::Attribute_31) { |                 attribute <= Attribute::Index::Attribute_31) { | ||||||
|                 declr_input_attribute.insert(attribute); |                 if (declr_input_attribute.count(attribute) == 0) { | ||||||
|  |                     declr_input_attribute[attribute] = input_mode; | ||||||
|  |                 } else { | ||||||
|  |                     if (declr_input_attribute[attribute] != input_mode) { | ||||||
|  |                         LOG_CRITICAL(HW_GPU, "Same Input multiple input modes"); | ||||||
|  |                         UNREACHABLE(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 return "input_attribute_" + std::to_string(index); |                 return "input_attribute_" + std::to_string(index); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -563,6 +586,49 @@ private: | |||||||
|         return "vec4(0, 0, 0, 0)"; |         return "vec4(0, 0, 0, 0)"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     std::string GetInputFlags(const Attribute::Index attribute) { | ||||||
|  |         const Tegra::Shader::IpaSampleMode sample_mode = | ||||||
|  |             declr_input_attribute[attribute].sampling_mode; | ||||||
|  |         const Tegra::Shader::IpaInterpMode interp_mode = | ||||||
|  |             declr_input_attribute[attribute].interpolation_mode; | ||||||
|  |         std::string out; | ||||||
|  |         switch (interp_mode) { | ||||||
|  |         case Tegra::Shader::IpaInterpMode::Flat: { | ||||||
|  |             out += "flat "; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case Tegra::Shader::IpaInterpMode::Linear: { | ||||||
|  |             out += "noperspective "; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case Tegra::Shader::IpaInterpMode::Perspective: { | ||||||
|  |             // Default, Smooth
 | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         default: { | ||||||
|  |             LOG_CRITICAL(HW_GPU, "Unhandled Ipa InterpMode: {}", static_cast<u32>(interp_mode)); | ||||||
|  |             UNREACHABLE(); | ||||||
|  |         } | ||||||
|  |         } | ||||||
|  |         switch (sample_mode) { | ||||||
|  |         case Tegra::Shader::IpaSampleMode::Centroid: { | ||||||
|  |             // Note not implemented, it can be implemented with the "centroid " keyword in glsl;
 | ||||||
|  |             LOG_CRITICAL(HW_GPU, "Ipa Sampler Mode: centroid, not implemented"); | ||||||
|  |             UNREACHABLE(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case Tegra::Shader::IpaSampleMode::Default: { | ||||||
|  |             // Default, n/a
 | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         default: { | ||||||
|  |             LOG_CRITICAL(HW_GPU, "Unhandled Ipa SampleMode: {}", static_cast<u32>(sample_mode)); | ||||||
|  |             UNREACHABLE(); | ||||||
|  |         } | ||||||
|  |         } | ||||||
|  |         return out; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Generates code representing an output attribute register.
 |     /// Generates code representing an output attribute register.
 | ||||||
|     std::string GetOutputAttribute(Attribute::Index attribute) { |     std::string GetOutputAttribute(Attribute::Index attribute) { | ||||||
|         switch (attribute) { |         switch (attribute) { | ||||||
| @ -593,7 +659,7 @@ private: | |||||||
|     ShaderWriter& shader; |     ShaderWriter& shader; | ||||||
|     ShaderWriter& declarations; |     ShaderWriter& declarations; | ||||||
|     std::vector<GLSLRegister> regs; |     std::vector<GLSLRegister> regs; | ||||||
|     std::set<Attribute::Index> declr_input_attribute; |     std::unordered_map<Attribute::Index, Tegra::Shader::IpaMode> 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; | ||||||
|     std::vector<SamplerEntry> used_samplers; |     std::vector<SamplerEntry> used_samplers; | ||||||
| @ -1634,8 +1700,12 @@ private: | |||||||
|             switch (opcode->GetId()) { |             switch (opcode->GetId()) { | ||||||
|             case OpCode::Id::LD_A: { |             case OpCode::Id::LD_A: { | ||||||
|                 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); |                 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested"); | ||||||
|  |                 // Note: Shouldn't this be interp mode flat? As in no interpolation made.
 | ||||||
|  | 
 | ||||||
|  |                 Tegra::Shader::IpaMode input_mode{Tegra::Shader::IpaInterpMode::Perspective, | ||||||
|  |                                                   Tegra::Shader::IpaSampleMode::Default}; | ||||||
|                 regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element, |                 regs.SetRegisterToInputAttibute(instr.gpr0, instr.attribute.fmt20.element, | ||||||
|                                                 instr.attribute.fmt20.index); |                                                 instr.attribute.fmt20.index, input_mode); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::LD_C: { |             case OpCode::Id::LD_C: { | ||||||
| @ -2127,42 +2197,11 @@ private: | |||||||
|             case OpCode::Id::IPA: { |             case OpCode::Id::IPA: { | ||||||
|                 const auto& attribute = instr.attribute.fmt28; |                 const auto& attribute = instr.attribute.fmt28; | ||||||
|                 const auto& reg = instr.gpr0; |                 const auto& reg = instr.gpr0; | ||||||
|                 ASSERT_MSG(instr.ipa.sample_mode == Tegra::Shader::IpaSampleMode::Default, |  | ||||||
|                            "Unhandled IPA sample mode: {}", |  | ||||||
|                            static_cast<u32>(instr.ipa.sample_mode.Value())); |  | ||||||
|                 ASSERT_MSG(instr.ipa.saturate == 0, "IPA saturate not implemented"); |                 ASSERT_MSG(instr.ipa.saturate == 0, "IPA saturate not implemented"); | ||||||
|                 switch (instr.ipa.interp_mode) { |                 Tegra::Shader::IpaMode input_mode{instr.ipa.interp_mode.Value(), | ||||||
|                 case Tegra::Shader::IpaInterpMode::Linear: |                                                   instr.ipa.sample_mode.Value()}; | ||||||
|                     if (stage == Maxwell3D::Regs::ShaderStage::Fragment && |                 regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index, | ||||||
|                         attribute.index == Attribute::Index::Position) { |                                                 input_mode); | ||||||
|                         switch (attribute.element) { |  | ||||||
|                         case 0: |  | ||||||
|                             shader.AddLine(regs.GetRegisterAsFloat(reg) + " = gl_FragCoord.x;"); |  | ||||||
|                             break; |  | ||||||
|                         case 1: |  | ||||||
|                             shader.AddLine(regs.GetRegisterAsFloat(reg) + " = gl_FragCoord.y;"); |  | ||||||
|                             break; |  | ||||||
|                         case 2: |  | ||||||
|                             shader.AddLine(regs.GetRegisterAsFloat(reg) + " = gl_FragCoord.z;"); |  | ||||||
|                             break; |  | ||||||
|                         case 3: |  | ||||||
|                             shader.AddLine(regs.GetRegisterAsFloat(reg) + " = 1.0;"); |  | ||||||
|                             break; |  | ||||||
|                         } |  | ||||||
|                     } else { |  | ||||||
|                         regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index); |  | ||||||
|                     } |  | ||||||
|                     break; |  | ||||||
|                 case Tegra::Shader::IpaInterpMode::Perspective: |  | ||||||
|                     regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index); |  | ||||||
|                     break; |  | ||||||
|                 default: |  | ||||||
|                     LOG_CRITICAL(HW_GPU, "Unhandled IPA mode: {}", |  | ||||||
|                                  static_cast<u32>(instr.ipa.interp_mode.Value())); |  | ||||||
|                     UNREACHABLE(); |  | ||||||
|                     regs.SetRegisterToInputAttibute(reg, attribute.element, attribute.index); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             case OpCode::Id::SSY: { |             case OpCode::Id::SSY: { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 FernandoS27
						FernandoS27