mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	gl_shader_decompiler: Implement GLSL physical attributes
This commit is contained in:
		
							parent
							
								
									71aa9d0877
								
							
						
					
					
						commit
						c6f9e651b2
					
				| @ -165,6 +165,7 @@ public: | |||||||
|         DeclareConstantBuffers(); |         DeclareConstantBuffers(); | ||||||
|         DeclareGlobalMemory(); |         DeclareGlobalMemory(); | ||||||
|         DeclareSamplers(); |         DeclareSamplers(); | ||||||
|  |         DeclarePhysicalAttributeReader(); | ||||||
| 
 | 
 | ||||||
|         code.AddLine("void execute_" + suffix + "() {"); |         code.AddLine("void execute_" + suffix + "() {"); | ||||||
|         ++code.scope; |         ++code.scope; | ||||||
| @ -330,8 +331,7 @@ private: | |||||||
| 
 | 
 | ||||||
|     void DeclareInputAttributes() { |     void DeclareInputAttributes() { | ||||||
|         if (ir.HasPhysicalAttributes()) { |         if (ir.HasPhysicalAttributes()) { | ||||||
|             const u32 num_inputs{stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() |             const u32 num_inputs{GetNumPhysicalInputAttributes()}; | ||||||
|                                                               : GetNumPhysicalVaryings()}; |  | ||||||
|             for (u32 i = 0; i < num_inputs; ++i) { |             for (u32 i = 0; i < num_inputs; ++i) { | ||||||
|                 DeclareInputAttribute(ToGenericAttribute(i)); |                 DeclareInputAttribute(ToGenericAttribute(i)); | ||||||
|             } |             } | ||||||
| @ -374,7 +374,7 @@ private: | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void DeclareOutputAttributes() { |     void DeclareOutputAttributes() { | ||||||
|         if (ir.HasPhysicalAttributes()) { |         if (ir.HasPhysicalAttributes() && stage != ShaderStage::Fragment) { | ||||||
|             for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) { |             for (u32 i = 0; i < GetNumPhysicalVaryings(); ++i) { | ||||||
|                 DeclareOutputAttribute(ToGenericAttribute(i)); |                 DeclareOutputAttribute(ToGenericAttribute(i)); | ||||||
|             } |             } | ||||||
| @ -461,6 +461,31 @@ private: | |||||||
|             code.AddNewLine(); |             code.AddNewLine(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     void DeclarePhysicalAttributeReader() { | ||||||
|  |         if (!ir.HasPhysicalAttributes()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         code.AddLine("float readPhysicalAttribute(uint physical_address) {"); | ||||||
|  |         ++code.scope; | ||||||
|  |         code.AddLine("switch (physical_address) {"); | ||||||
|  | 
 | ||||||
|  |         // Just declare generic attributes for now.
 | ||||||
|  |         const auto num_attributes{static_cast<u32>(GetNumPhysicalAttributes())}; | ||||||
|  |         for (u32 index = 0; index < num_attributes; ++index) { | ||||||
|  |             for (u32 element = 0; element < 4; ++element) { | ||||||
|  |                 code.AddLine(fmt::format("case 0x{:x}: return {};", 0x80 + index * 16 + element * 4, | ||||||
|  |                                          ReadAttribute(ToGenericAttribute(index), element))); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         code.AddLine("default: return 0;"); | ||||||
|  | 
 | ||||||
|  |         code.AddLine('}'); | ||||||
|  |         --code.scope; | ||||||
|  |         code.AddLine('}'); | ||||||
|  |         code.AddNewLine(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void VisitBlock(const NodeBlock& bb) { |     void VisitBlock(const NodeBlock& bb) { | ||||||
|         for (const Node node : bb) { |         for (const Node node : bb) { | ||||||
|             if (const std::string expr = Visit(node); !expr.empty()) { |             if (const std::string expr = Visit(node); !expr.empty()) { | ||||||
| @ -515,69 +540,12 @@ private: | |||||||
|             return value; |             return value; | ||||||
| 
 | 
 | ||||||
|         } else if (const auto abuf = std::get_if<AbufNode>(node)) { |         } else if (const auto abuf = std::get_if<AbufNode>(node)) { | ||||||
|             const auto attribute = abuf->GetIndex(); |             UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry, | ||||||
|             const auto element = abuf->GetElement(); |                                  "Physical attributes in geometry shaders are not implemented"); | ||||||
| 
 |             if (abuf->IsPhysicalBuffer()) { | ||||||
|             const auto GeometryPass = [&](const std::string& name) { |                 return "readPhysicalAttribute(ftou(" + Visit(abuf->GetPhysicalAddress()) + "))"; | ||||||
|                 if (stage == ShaderStage::Geometry && abuf->GetBuffer()) { |  | ||||||
|                     // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
 |  | ||||||
|                     // set an 0x80000000 index for those and the shader fails to build. Find out why
 |  | ||||||
|                     // this happens and what's its intent.
 |  | ||||||
|                     return "gs_" + name + "[ftou(" + Visit(abuf->GetBuffer()) + |  | ||||||
|                            ") % MAX_VERTEX_INPUT]"; |  | ||||||
|                 } |  | ||||||
|                 return name; |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|             switch (attribute) { |  | ||||||
|             case Attribute::Index::Position: |  | ||||||
|                 if (stage != ShaderStage::Fragment) { |  | ||||||
|                     return GeometryPass("position") + GetSwizzle(element); |  | ||||||
|                 } else { |  | ||||||
|                     return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element); |  | ||||||
|                 } |  | ||||||
|             case Attribute::Index::PointCoord: |  | ||||||
|                 switch (element) { |  | ||||||
|                 case 0: |  | ||||||
|                     return "gl_PointCoord.x"; |  | ||||||
|                 case 1: |  | ||||||
|                     return "gl_PointCoord.y"; |  | ||||||
|                 case 2: |  | ||||||
|                 case 3: |  | ||||||
|                     return "0"; |  | ||||||
|                 } |  | ||||||
|                 UNREACHABLE(); |  | ||||||
|                 return "0"; |  | ||||||
|             case Attribute::Index::TessCoordInstanceIDVertexID: |  | ||||||
|                 // 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
 |  | ||||||
|                 // shader.
 |  | ||||||
|                 ASSERT(stage == ShaderStage::Vertex); |  | ||||||
|                 switch (element) { |  | ||||||
|                 case 2: |  | ||||||
|                     // Config pack's first value is instance_id.
 |  | ||||||
|                     return "uintBitsToFloat(config_pack[0])"; |  | ||||||
|                 case 3: |  | ||||||
|                     return "uintBitsToFloat(gl_VertexID)"; |  | ||||||
|                 } |  | ||||||
|                 UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element); |  | ||||||
|                 return "0"; |  | ||||||
|             case Attribute::Index::FrontFacing: |  | ||||||
|                 // TODO(Subv): Find out what the values are for the other elements.
 |  | ||||||
|                 ASSERT(stage == ShaderStage::Fragment); |  | ||||||
|                 switch (element) { |  | ||||||
|                 case 3: |  | ||||||
|                     return "itof(gl_FrontFacing ? -1 : 0)"; |  | ||||||
|                 } |  | ||||||
|                 UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element); |  | ||||||
|                 return "0"; |  | ||||||
|             default: |  | ||||||
|                 if (IsGenericAttribute(attribute)) { |  | ||||||
|                     return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element); |  | ||||||
|                 } |  | ||||||
|                 break; |  | ||||||
|             } |             } | ||||||
|             UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); |             return ReadAttribute(abuf->GetIndex(), abuf->GetElement(), abuf->GetBuffer()); | ||||||
| 
 | 
 | ||||||
|         } else if (const auto cbuf = std::get_if<CbufNode>(node)) { |         } else if (const auto cbuf = std::get_if<CbufNode>(node)) { | ||||||
|             const Node offset = cbuf->GetOffset(); |             const Node offset = cbuf->GetOffset(); | ||||||
| @ -629,6 +597,69 @@ private: | |||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     std::string ReadAttribute(Attribute::Index attribute, u32 element, Node buffer = {}) { | ||||||
|  |         const auto GeometryPass = [&](std::string name) { | ||||||
|  |             if (stage == ShaderStage::Geometry && buffer) { | ||||||
|  |                 // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
 | ||||||
|  |                 // set an 0x80000000 index for those and the shader fails to build. Find out why
 | ||||||
|  |                 // this happens and what's its intent.
 | ||||||
|  |                 return "gs_" + std::move(name) + "[ftou(" + Visit(buffer) + ") % MAX_VERTEX_INPUT]"; | ||||||
|  |             } | ||||||
|  |             return name; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         switch (attribute) { | ||||||
|  |         case Attribute::Index::Position: | ||||||
|  |             if (stage != ShaderStage::Fragment) { | ||||||
|  |                 return GeometryPass("position") + GetSwizzle(element); | ||||||
|  |             } else { | ||||||
|  |                 return element == 3 ? "1.0f" : "gl_FragCoord" + GetSwizzle(element); | ||||||
|  |             } | ||||||
|  |         case Attribute::Index::PointCoord: | ||||||
|  |             switch (element) { | ||||||
|  |             case 0: | ||||||
|  |                 return "gl_PointCoord.x"; | ||||||
|  |             case 1: | ||||||
|  |                 return "gl_PointCoord.y"; | ||||||
|  |             case 2: | ||||||
|  |             case 3: | ||||||
|  |                 return "0"; | ||||||
|  |             } | ||||||
|  |             UNREACHABLE(); | ||||||
|  |             return "0"; | ||||||
|  |         case Attribute::Index::TessCoordInstanceIDVertexID: | ||||||
|  |             // 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
 | ||||||
|  |             // shader.
 | ||||||
|  |             ASSERT(stage == ShaderStage::Vertex); | ||||||
|  |             switch (element) { | ||||||
|  |             case 2: | ||||||
|  |                 // Config pack's first value is instance_id.
 | ||||||
|  |                 return "uintBitsToFloat(config_pack[0])"; | ||||||
|  |             case 3: | ||||||
|  |                 return "uintBitsToFloat(gl_VertexID)"; | ||||||
|  |             } | ||||||
|  |             UNIMPLEMENTED_MSG("Unmanaged TessCoordInstanceIDVertexID element={}", element); | ||||||
|  |             return "0"; | ||||||
|  |         case Attribute::Index::FrontFacing: | ||||||
|  |             // TODO(Subv): Find out what the values are for the other elements.
 | ||||||
|  |             ASSERT(stage == ShaderStage::Fragment); | ||||||
|  |             switch (element) { | ||||||
|  |             case 3: | ||||||
|  |                 return "itof(gl_FrontFacing ? -1 : 0)"; | ||||||
|  |             } | ||||||
|  |             UNIMPLEMENTED_MSG("Unmanaged FrontFacing element={}", element); | ||||||
|  |             return "0"; | ||||||
|  |         default: | ||||||
|  |             if (IsGenericAttribute(attribute)) { | ||||||
|  |                 return GeometryPass(GetInputAttribute(attribute)) + GetSwizzle(element); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); | ||||||
|  |         return "0"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     std::string ApplyPrecise(Operation operation, const std::string& value) { |     std::string ApplyPrecise(Operation operation, const std::string& value) { | ||||||
|         if (!IsPrecise(operation)) { |         if (!IsPrecise(operation)) { | ||||||
|             return value; |             return value; | ||||||
| @ -1677,6 +1708,10 @@ private: | |||||||
|         return name + '_' + std::to_string(index) + '_' + suffix; |         return name + '_' + std::to_string(index) + '_' + suffix; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     u32 GetNumPhysicalInputAttributes() const { | ||||||
|  |         return stage == ShaderStage::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     u32 GetNumPhysicalAttributes() const { |     u32 GetNumPhysicalAttributes() const { | ||||||
|         return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes); |         return std::min<u32>(device.GetMaxVertexAttributes(), Maxwell::NumVertexAttributes); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -885,7 +885,7 @@ private: | |||||||
|     std::set<Sampler> used_samplers; |     std::set<Sampler> used_samplers; | ||||||
|     std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; |     std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; | ||||||
|     std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; |     std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; | ||||||
|     bool use_physical_attributes = true; // Shader uses AL2P
 |     bool use_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
 | ||||||
| 
 | 
 | ||||||
|     Tegra::Shader::Header header; |     Tegra::Shader::Header header; | ||||||
| }; | }; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
						ReinUsesLisp