mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	VideoCore/Shader: Move DebugData to a separate file
This commit is contained in:
		
							parent
							
								
									cda7210fad
								
							
						
					
					
						commit
						d27cb1dedc
					
				
					 4 changed files with 189 additions and 172 deletions
				
			
		|  | @ -39,6 +39,7 @@ set(HEADERS | ||||||
|             rasterizer.h |             rasterizer.h | ||||||
|             rasterizer_interface.h |             rasterizer_interface.h | ||||||
|             renderer_base.h |             renderer_base.h | ||||||
|  |             shader/debug_data.h | ||||||
|             shader/shader.h |             shader/shader.h | ||||||
|             shader/shader_interpreter.h |             shader/shader_interpreter.h | ||||||
|             swrasterizer.h |             swrasterizer.h | ||||||
|  |  | ||||||
							
								
								
									
										186
									
								
								src/video_core/shader/debug_data.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								src/video_core/shader/debug_data.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,186 @@ | ||||||
|  | // Copyright 2016 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "common/vector_math.h" | ||||||
|  | #include "video_core/pica_types.h" | ||||||
|  | 
 | ||||||
|  | namespace Pica { | ||||||
|  | namespace Shader { | ||||||
|  | 
 | ||||||
|  | /// Helper structure used to keep track of data useful for inspection of shader emulation
 | ||||||
|  | template <bool full_debugging> | ||||||
|  | struct DebugData; | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | struct DebugData<false> { | ||||||
|  |     // TODO: Hide these behind and interface and move them to DebugData<true>
 | ||||||
|  |     u32 max_offset;    ///< maximum program counter ever reached
 | ||||||
|  |     u32 max_opdesc_id; ///< maximum swizzle pattern index ever used
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | struct DebugData<true> { | ||||||
|  |     /// Records store the input and output operands of a particular instruction.
 | ||||||
|  |     struct Record { | ||||||
|  |         enum Type { | ||||||
|  |             // Floating point arithmetic operands
 | ||||||
|  |             SRC1 = 0x1, | ||||||
|  |             SRC2 = 0x2, | ||||||
|  |             SRC3 = 0x4, | ||||||
|  | 
 | ||||||
|  |             // Initial and final output operand value
 | ||||||
|  |             DEST_IN = 0x8, | ||||||
|  |             DEST_OUT = 0x10, | ||||||
|  | 
 | ||||||
|  |             // Current and next instruction offset (in words)
 | ||||||
|  |             CUR_INSTR = 0x20, | ||||||
|  |             NEXT_INSTR = 0x40, | ||||||
|  | 
 | ||||||
|  |             // Output address register value
 | ||||||
|  |             ADDR_REG_OUT = 0x80, | ||||||
|  | 
 | ||||||
|  |             // Result of a comparison instruction
 | ||||||
|  |             CMP_RESULT = 0x100, | ||||||
|  | 
 | ||||||
|  |             // Input values for conditional flow control instructions
 | ||||||
|  |             COND_BOOL_IN = 0x200, | ||||||
|  |             COND_CMP_IN = 0x400, | ||||||
|  | 
 | ||||||
|  |             // Input values for a loop
 | ||||||
|  |             LOOP_INT_IN = 0x800, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         Math::Vec4<float24> src1; | ||||||
|  |         Math::Vec4<float24> src2; | ||||||
|  |         Math::Vec4<float24> src3; | ||||||
|  | 
 | ||||||
|  |         Math::Vec4<float24> dest_in; | ||||||
|  |         Math::Vec4<float24> dest_out; | ||||||
|  | 
 | ||||||
|  |         s32 address_registers[2]; | ||||||
|  |         bool conditional_code[2]; | ||||||
|  |         bool cond_bool; | ||||||
|  |         bool cond_cmp[2]; | ||||||
|  |         Math::Vec4<u8> loop_int; | ||||||
|  | 
 | ||||||
|  |         u32 instruction_offset; | ||||||
|  |         u32 next_instruction; | ||||||
|  | 
 | ||||||
|  |         /// set of enabled fields (as a combination of Type flags)
 | ||||||
|  |         unsigned mask = 0; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     u32 max_offset;    ///< maximum program counter ever reached
 | ||||||
|  |     u32 max_opdesc_id; ///< maximum swizzle pattern index ever used
 | ||||||
|  | 
 | ||||||
|  |     /// List of records for each executed shader instruction
 | ||||||
|  |     std::vector<DebugData<true>::Record> records; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /// Type alias for better readability
 | ||||||
|  | using DebugDataRecord = DebugData<true>::Record; | ||||||
|  | 
 | ||||||
|  | /// Helper function to set a DebugData<true>::Record field based on the template enum parameter.
 | ||||||
|  | template <DebugDataRecord::Type type, typename ValueType> | ||||||
|  | inline void SetField(DebugDataRecord& record, ValueType value); | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::SRC1>(DebugDataRecord& record, float24* value) { | ||||||
|  |     record.src1.x = value[0]; | ||||||
|  |     record.src1.y = value[1]; | ||||||
|  |     record.src1.z = value[2]; | ||||||
|  |     record.src1.w = value[3]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::SRC2>(DebugDataRecord& record, float24* value) { | ||||||
|  |     record.src2.x = value[0]; | ||||||
|  |     record.src2.y = value[1]; | ||||||
|  |     record.src2.z = value[2]; | ||||||
|  |     record.src2.w = value[3]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::SRC3>(DebugDataRecord& record, float24* value) { | ||||||
|  |     record.src3.x = value[0]; | ||||||
|  |     record.src3.y = value[1]; | ||||||
|  |     record.src3.z = value[2]; | ||||||
|  |     record.src3.w = value[3]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::DEST_IN>(DebugDataRecord& record, float24* value) { | ||||||
|  |     record.dest_in.x = value[0]; | ||||||
|  |     record.dest_in.y = value[1]; | ||||||
|  |     record.dest_in.z = value[2]; | ||||||
|  |     record.dest_in.w = value[3]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::DEST_OUT>(DebugDataRecord& record, float24* value) { | ||||||
|  |     record.dest_out.x = value[0]; | ||||||
|  |     record.dest_out.y = value[1]; | ||||||
|  |     record.dest_out.z = value[2]; | ||||||
|  |     record.dest_out.w = value[3]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::ADDR_REG_OUT>(DebugDataRecord& record, s32* value) { | ||||||
|  |     record.address_registers[0] = value[0]; | ||||||
|  |     record.address_registers[1] = value[1]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::CMP_RESULT>(DebugDataRecord& record, bool* value) { | ||||||
|  |     record.conditional_code[0] = value[0]; | ||||||
|  |     record.conditional_code[1] = value[1]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::COND_BOOL_IN>(DebugDataRecord& record, bool value) { | ||||||
|  |     record.cond_bool = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::COND_CMP_IN>(DebugDataRecord& record, bool* value) { | ||||||
|  |     record.cond_cmp[0] = value[0]; | ||||||
|  |     record.cond_cmp[1] = value[1]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::LOOP_INT_IN>(DebugDataRecord& record, Math::Vec4<u8> value) { | ||||||
|  |     record.loop_int = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::CUR_INSTR>(DebugDataRecord& record, u32 value) { | ||||||
|  |     record.instruction_offset = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <> | ||||||
|  | inline void SetField<DebugDataRecord::NEXT_INSTR>(DebugDataRecord& record, u32 value) { | ||||||
|  |     record.next_instruction = value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Helper function to set debug information on the current shader iteration.
 | ||||||
|  | template <DebugDataRecord::Type type, typename ValueType> | ||||||
|  | inline void Record(DebugData<false>& debug_data, u32 offset, ValueType value) { | ||||||
|  |     // Debugging disabled => nothing to do
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <DebugDataRecord::Type type, typename ValueType> | ||||||
|  | inline void Record(DebugData<true>& debug_data, u32 offset, ValueType value) { | ||||||
|  |     if (offset >= debug_data.records.size()) | ||||||
|  |         debug_data.records.resize(offset + 1); | ||||||
|  | 
 | ||||||
|  |     SetField<type, ValueType>(debug_data.records[offset], value); | ||||||
|  |     debug_data.records[offset].mask |= type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Shader
 | ||||||
|  | } // namespace Pica
 | ||||||
|  | @ -8,8 +8,6 @@ | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
| #include <vector> |  | ||||||
| #include <boost/container/static_vector.hpp> |  | ||||||
| #include <nihstro/shader_bytecode.h> | #include <nihstro/shader_bytecode.h> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_funcs.h" | #include "common/common_funcs.h" | ||||||
|  | @ -17,6 +15,7 @@ | ||||||
| #include "common/vector_math.h" | #include "common/vector_math.h" | ||||||
| #include "video_core/pica.h" | #include "video_core/pica.h" | ||||||
| #include "video_core/pica_types.h" | #include "video_core/pica_types.h" | ||||||
|  | #include "video_core/shader/debug_data.h" | ||||||
| 
 | 
 | ||||||
| using nihstro::RegisterType; | using nihstro::RegisterType; | ||||||
| using nihstro::SourceRegister; | using nihstro::SourceRegister; | ||||||
|  | @ -89,176 +88,6 @@ struct OutputRegisters { | ||||||
| }; | }; | ||||||
| static_assert(std::is_pod<OutputRegisters>::value, "Structure is not POD"); | static_assert(std::is_pod<OutputRegisters>::value, "Structure is not POD"); | ||||||
| 
 | 
 | ||||||
| // Helper structure used to keep track of data useful for inspection of shader emulation
 |  | ||||||
| template <bool full_debugging> |  | ||||||
| struct DebugData; |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| struct DebugData<false> { |  | ||||||
|     // TODO: Hide these behind and interface and move them to DebugData<true>
 |  | ||||||
|     u32 max_offset;    // maximum program counter ever reached
 |  | ||||||
|     u32 max_opdesc_id; // maximum swizzle pattern index ever used
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| struct DebugData<true> { |  | ||||||
|     // Records store the input and output operands of a particular instruction.
 |  | ||||||
|     struct Record { |  | ||||||
|         enum Type { |  | ||||||
|             // Floating point arithmetic operands
 |  | ||||||
|             SRC1 = 0x1, |  | ||||||
|             SRC2 = 0x2, |  | ||||||
|             SRC3 = 0x4, |  | ||||||
| 
 |  | ||||||
|             // Initial and final output operand value
 |  | ||||||
|             DEST_IN = 0x8, |  | ||||||
|             DEST_OUT = 0x10, |  | ||||||
| 
 |  | ||||||
|             // Current and next instruction offset (in words)
 |  | ||||||
|             CUR_INSTR = 0x20, |  | ||||||
|             NEXT_INSTR = 0x40, |  | ||||||
| 
 |  | ||||||
|             // Output address register value
 |  | ||||||
|             ADDR_REG_OUT = 0x80, |  | ||||||
| 
 |  | ||||||
|             // Result of a comparison instruction
 |  | ||||||
|             CMP_RESULT = 0x100, |  | ||||||
| 
 |  | ||||||
|             // Input values for conditional flow control instructions
 |  | ||||||
|             COND_BOOL_IN = 0x200, |  | ||||||
|             COND_CMP_IN = 0x400, |  | ||||||
| 
 |  | ||||||
|             // Input values for a loop
 |  | ||||||
|             LOOP_INT_IN = 0x800, |  | ||||||
|         }; |  | ||||||
| 
 |  | ||||||
|         Math::Vec4<float24> src1; |  | ||||||
|         Math::Vec4<float24> src2; |  | ||||||
|         Math::Vec4<float24> src3; |  | ||||||
| 
 |  | ||||||
|         Math::Vec4<float24> dest_in; |  | ||||||
|         Math::Vec4<float24> dest_out; |  | ||||||
| 
 |  | ||||||
|         s32 address_registers[2]; |  | ||||||
|         bool conditional_code[2]; |  | ||||||
|         bool cond_bool; |  | ||||||
|         bool cond_cmp[2]; |  | ||||||
|         Math::Vec4<u8> loop_int; |  | ||||||
| 
 |  | ||||||
|         u32 instruction_offset; |  | ||||||
|         u32 next_instruction; |  | ||||||
| 
 |  | ||||||
|         // set of enabled fields (as a combination of Type flags)
 |  | ||||||
|         unsigned mask = 0; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     u32 max_offset;    // maximum program counter ever reached
 |  | ||||||
|     u32 max_opdesc_id; // maximum swizzle pattern index ever used
 |  | ||||||
| 
 |  | ||||||
|     // List of records for each executed shader instruction
 |  | ||||||
|     std::vector<DebugData<true>::Record> records; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // Type alias for better readability
 |  | ||||||
| using DebugDataRecord = DebugData<true>::Record; |  | ||||||
| 
 |  | ||||||
| // Helper function to set a DebugData<true>::Record field based on the template enum parameter.
 |  | ||||||
| template <DebugDataRecord::Type type, typename ValueType> |  | ||||||
| inline void SetField(DebugDataRecord& record, ValueType value); |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::SRC1>(DebugDataRecord& record, float24* value) { |  | ||||||
|     record.src1.x = value[0]; |  | ||||||
|     record.src1.y = value[1]; |  | ||||||
|     record.src1.z = value[2]; |  | ||||||
|     record.src1.w = value[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::SRC2>(DebugDataRecord& record, float24* value) { |  | ||||||
|     record.src2.x = value[0]; |  | ||||||
|     record.src2.y = value[1]; |  | ||||||
|     record.src2.z = value[2]; |  | ||||||
|     record.src2.w = value[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::SRC3>(DebugDataRecord& record, float24* value) { |  | ||||||
|     record.src3.x = value[0]; |  | ||||||
|     record.src3.y = value[1]; |  | ||||||
|     record.src3.z = value[2]; |  | ||||||
|     record.src3.w = value[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::DEST_IN>(DebugDataRecord& record, float24* value) { |  | ||||||
|     record.dest_in.x = value[0]; |  | ||||||
|     record.dest_in.y = value[1]; |  | ||||||
|     record.dest_in.z = value[2]; |  | ||||||
|     record.dest_in.w = value[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::DEST_OUT>(DebugDataRecord& record, float24* value) { |  | ||||||
|     record.dest_out.x = value[0]; |  | ||||||
|     record.dest_out.y = value[1]; |  | ||||||
|     record.dest_out.z = value[2]; |  | ||||||
|     record.dest_out.w = value[3]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::ADDR_REG_OUT>(DebugDataRecord& record, s32* value) { |  | ||||||
|     record.address_registers[0] = value[0]; |  | ||||||
|     record.address_registers[1] = value[1]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::CMP_RESULT>(DebugDataRecord& record, bool* value) { |  | ||||||
|     record.conditional_code[0] = value[0]; |  | ||||||
|     record.conditional_code[1] = value[1]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::COND_BOOL_IN>(DebugDataRecord& record, bool value) { |  | ||||||
|     record.cond_bool = value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::COND_CMP_IN>(DebugDataRecord& record, bool* value) { |  | ||||||
|     record.cond_cmp[0] = value[0]; |  | ||||||
|     record.cond_cmp[1] = value[1]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::LOOP_INT_IN>(DebugDataRecord& record, Math::Vec4<u8> value) { |  | ||||||
|     record.loop_int = value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::CUR_INSTR>(DebugDataRecord& record, u32 value) { |  | ||||||
|     record.instruction_offset = value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <> |  | ||||||
| inline void SetField<DebugDataRecord::NEXT_INSTR>(DebugDataRecord& record, u32 value) { |  | ||||||
|     record.next_instruction = value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Helper function to set debug information on the current shader iteration.
 |  | ||||||
| template <DebugDataRecord::Type type, typename ValueType> |  | ||||||
| inline void Record(DebugData<false>& debug_data, u32 offset, ValueType value) { |  | ||||||
|     // Debugging disabled => nothing to do
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <DebugDataRecord::Type type, typename ValueType> |  | ||||||
| inline void Record(DebugData<true>& debug_data, u32 offset, ValueType value) { |  | ||||||
|     if (offset >= debug_data.records.size()) |  | ||||||
|         debug_data.records.resize(offset + 1); |  | ||||||
| 
 |  | ||||||
|     SetField<type, ValueType>(debug_data.records[offset], value); |  | ||||||
|     debug_data.records[offset].mask |= type; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * This structure contains the state information that needs to be unique for a shader unit. The 3DS |  * This structure contains the state information that needs to be unique for a shader unit. The 3DS | ||||||
|  * has four shader units that process shaders in parallel. At the present, Citra only implements a |  * has four shader units that process shaders in parallel. At the present, Citra only implements a | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include <array> | #include <array> | ||||||
| #include <cmath> | #include <cmath> | ||||||
| #include <numeric> | #include <numeric> | ||||||
|  | #include <boost/container/static_vector.hpp> | ||||||
| #include <nihstro/shader_bytecode.h> | #include <nihstro/shader_bytecode.h> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue