mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 22:00:05 +00:00 
			
		
		
		
	video_core serialization
This commit is contained in:
		
							parent
							
								
									ee2cae2093
								
							
						
					
					
						commit
						6f00976ab5
					
				
					 9 changed files with 142 additions and 21 deletions
				
			
		|  | @ -1,11 +1,14 @@ | ||||||
| #include "boost/archive/binary_iarchive.hpp" | #include "boost/archive/binary_iarchive.hpp" | ||||||
| #include "boost/archive/binary_oarchive.hpp" | #include "boost/archive/binary_oarchive.hpp" | ||||||
| 
 | 
 | ||||||
| #define SERIALIZE_IMPL(A) template void A::serialize<boost::archive::binary_iarchive>( \ | using iarchive = boost::archive::binary_iarchive; | ||||||
|     boost::archive::binary_iarchive & ar, \ | using oarchive = boost::archive::binary_oarchive; | ||||||
|  | 
 | ||||||
|  | #define SERIALIZE_IMPL(A) template void A::serialize<iarchive>( \ | ||||||
|  |     iarchive & ar, \ | ||||||
|     const unsigned int file_version \ |     const unsigned int file_version \ | ||||||
| ); \ | ); \ | ||||||
| template void A::serialize<boost::archive::binary_oarchive>( \ | template void A::serialize<oarchive>( \ | ||||||
|     boost::archive::binary_oarchive & ar, \ |     oarchive & ar, \ | ||||||
|     const unsigned int file_version \ |     const unsigned int file_version \ | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | @ -397,22 +397,28 @@ void System::Reset() { | ||||||
| template<class Archive> | template<class Archive> | ||||||
| void System::serialize(Archive & ar, const unsigned int file_version) | void System::serialize(Archive & ar, const unsigned int file_version) | ||||||
| { | { | ||||||
|     ar & memory; |  | ||||||
|     ar & GPU::g_regs; |     ar & GPU::g_regs; | ||||||
|     ar & LCD::g_regs; |     ar & LCD::g_regs; | ||||||
|     ar & dsp_core->GetDspMemory(); |     ar & dsp_core->GetDspMemory(); | ||||||
|  |     ar & memory; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void System::Save(std::ostream &stream) const | void System::Save(std::ostream &stream) const | ||||||
| { | { | ||||||
|     boost::archive::binary_oarchive oa{stream}; |     { | ||||||
|  |         oarchive oa{stream}; | ||||||
|         oa & *this; |         oa & *this; | ||||||
|     } |     } | ||||||
|  |     VideoCore::Save(stream); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void System::Load(std::istream &stream) | void System::Load(std::istream &stream) | ||||||
| { | { | ||||||
|     boost::archive::binary_iarchive ia{stream}; |     { | ||||||
|  |         iarchive ia{stream}; | ||||||
|         ia & *this; |         ia & *this; | ||||||
|     } |     } | ||||||
|  |     VideoCore::Load(stream); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| } // namespace Core
 | } // namespace Core
 | ||||||
|  |  | ||||||
|  | @ -472,14 +472,7 @@ inline void Write(u32 addr, const T data) { | ||||||
|         if (config.trigger & 1) { |         if (config.trigger & 1) { | ||||||
|             MICROPROFILE_SCOPE(GPU_CmdlistProcessing); |             MICROPROFILE_SCOPE(GPU_CmdlistProcessing); | ||||||
| 
 | 
 | ||||||
|             u32* buffer = (u32*)g_memory->GetPhysicalPointer(config.GetPhysicalAddress()); |             Pica::CommandProcessor::ProcessCommandList(config.GetPhysicalAddress(), config.size); | ||||||
| 
 |  | ||||||
|             if (Pica::g_debug_context && Pica::g_debug_context->recorder) { |  | ||||||
|                 Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, config.size, |  | ||||||
|                                                                 config.GetPhysicalAddress()); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             Pica::CommandProcessor::ProcessCommandList(buffer, config.size); |  | ||||||
| 
 | 
 | ||||||
|             g_regs.command_processor_config.trigger = 0; |             g_regs.command_processor_config.trigger = 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -94,7 +94,7 @@ endif() | ||||||
| create_target_directory_groups(video_core) | create_target_directory_groups(video_core) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(video_core PUBLIC common core) | target_link_libraries(video_core PUBLIC common core) | ||||||
| target_link_libraries(video_core PRIVATE glad nihstro-headers) | target_link_libraries(video_core PRIVATE glad nihstro-headers boost_libs) | ||||||
| 
 | 
 | ||||||
| if (ARCHITECTURE_x86_64) | if (ARCHITECTURE_x86_64) | ||||||
|     target_link_libraries(video_core PUBLIC xbyak) |     target_link_libraries(video_core PUBLIC xbyak) | ||||||
|  |  | ||||||
|  | @ -640,8 +640,17 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|                                  reinterpret_cast<void*>(&id)); |                                  reinterpret_cast<void*>(&id)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ProcessCommandList(const u32* list, u32 size) { | void ProcessCommandList(PAddr list, u32 size) { | ||||||
|     g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = list; | 
 | ||||||
|  |     u32* buffer = (u32*)VideoCore::g_memory->GetPhysicalPointer(list); | ||||||
|  | 
 | ||||||
|  |     if (Pica::g_debug_context && Pica::g_debug_context->recorder) { | ||||||
|  |         Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, size, | ||||||
|  |                                                         list); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     g_state.cmd_list.addr = list; | ||||||
|  |     g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = buffer; | ||||||
|     g_state.cmd_list.length = size / sizeof(u32); |     g_state.cmd_list.length = size / sizeof(u32); | ||||||
| 
 | 
 | ||||||
|     while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) { |     while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) { | ||||||
|  |  | ||||||
|  | @ -32,6 +32,6 @@ static_assert(std::is_standard_layout<CommandHeader>::value == true, | ||||||
|               "CommandHeader does not use standard layout"); |               "CommandHeader does not use standard layout"); | ||||||
| static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!"); | static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!"); | ||||||
| 
 | 
 | ||||||
| void ProcessCommandList(const u32* list, u32 size); | void ProcessCommandList(PAddr list, u32 size); | ||||||
| 
 | 
 | ||||||
| } // namespace Pica::CommandProcessor
 | } // namespace Pica::CommandProcessor
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <array> | #include <array> | ||||||
|  | #include "boost/serialization/split_member.hpp" | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/vector_math.h" | #include "common/vector_math.h" | ||||||
|  | @ -13,6 +14,18 @@ | ||||||
| #include "video_core/regs.h" | #include "video_core/regs.h" | ||||||
| #include "video_core/shader/shader.h" | #include "video_core/shader/shader.h" | ||||||
| 
 | 
 | ||||||
|  | // NB, by defining this we can't use the built-in std::array serializer in this file
 | ||||||
|  | namespace boost::serialization { | ||||||
|  | 
 | ||||||
|  | template<class Archive, typename Value, size_t Size> | ||||||
|  | void serialize(Archive & ar, std::array<Value, Size> &array, const unsigned int version) | ||||||
|  | { | ||||||
|  |     static_assert(sizeof(Value) == sizeof(u32)); | ||||||
|  |     ar & *static_cast<u32 (*)[Size]>(static_cast<void *>(array.data())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Pica { | namespace Pica { | ||||||
| 
 | 
 | ||||||
| /// Struct used to describe current Pica state
 | /// Struct used to describe current Pica state
 | ||||||
|  | @ -79,6 +92,18 @@ struct State { | ||||||
|         std::array<ValueEntry, 128> alpha_map_table; |         std::array<ValueEntry, 128> alpha_map_table; | ||||||
|         std::array<ColorEntry, 256> color_table; |         std::array<ColorEntry, 256> color_table; | ||||||
|         std::array<ColorDifferenceEntry, 256> color_diff_table; |         std::array<ColorDifferenceEntry, 256> color_diff_table; | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         friend class boost::serialization::access; | ||||||
|  |         template<class Archive> | ||||||
|  |         void serialize(Archive & ar, const unsigned int file_version) | ||||||
|  |         { | ||||||
|  |             ar & noise_table; | ||||||
|  |             ar & color_map_table; | ||||||
|  |             ar & alpha_map_table; | ||||||
|  |             ar & color_table; | ||||||
|  |             ar & color_diff_table; | ||||||
|  |         } | ||||||
|     } proctex; |     } proctex; | ||||||
| 
 | 
 | ||||||
|     struct Lighting { |     struct Lighting { | ||||||
|  | @ -101,6 +126,12 @@ struct State { | ||||||
|                 float diff = static_cast<float>(difference) / 2047.f; |                 float diff = static_cast<float>(difference) / 2047.f; | ||||||
|                 return neg_difference ? -diff : diff; |                 return neg_difference ? -diff : diff; | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             template<class Archive> | ||||||
|  |             void serialize(Archive & ar, const unsigned int file_version) | ||||||
|  |             { | ||||||
|  |                 ar & raw; | ||||||
|  |             } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         std::array<std::array<LutEntry, 256>, 24> luts; |         std::array<std::array<LutEntry, 256>, 24> luts; | ||||||
|  | @ -126,8 +157,11 @@ struct State { | ||||||
|         std::array<LutEntry, 128> lut; |         std::array<LutEntry, 128> lut; | ||||||
|     } fog; |     } fog; | ||||||
| 
 | 
 | ||||||
|  | #undef SERIALIZE_RAW | ||||||
|  | 
 | ||||||
|     /// Current Pica command list
 |     /// Current Pica command list
 | ||||||
|     struct { |     struct { | ||||||
|  |         PAddr addr; // This exists only for serialization
 | ||||||
|         const u32* head_ptr; |         const u32* head_ptr; | ||||||
|         const u32* current_ptr; |         const u32* current_ptr; | ||||||
|         u32 length; |         u32 length; | ||||||
|  | @ -141,6 +175,17 @@ struct State { | ||||||
|         u32 current_attribute = 0; |         u32 current_attribute = 0; | ||||||
|         // Indicates the immediate mode just started and the geometry pipeline needs to reconfigure
 |         // Indicates the immediate mode just started and the geometry pipeline needs to reconfigure
 | ||||||
|         bool reset_geometry_pipeline = true; |         bool reset_geometry_pipeline = true; | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  |         friend class boost::serialization::access; | ||||||
|  |         template<class Archive> | ||||||
|  |         void serialize(Archive & ar, const unsigned int file_version) | ||||||
|  |         { | ||||||
|  |             // ar & input_vertex;
 | ||||||
|  |             ar & current_attribute; | ||||||
|  |             ar & reset_geometry_pipeline; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|     } immediate; |     } immediate; | ||||||
| 
 | 
 | ||||||
|     // the geometry shader needs to be kept in the global state because some shaders relie on
 |     // the geometry shader needs to be kept in the global state because some shaders relie on
 | ||||||
|  | @ -161,6 +206,51 @@ struct State { | ||||||
| 
 | 
 | ||||||
|     int default_attr_counter = 0; |     int default_attr_counter = 0; | ||||||
|     u32 default_attr_write_buffer[3]{}; |     u32 default_attr_write_buffer[3]{}; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |     friend class boost::serialization::access; | ||||||
|  |     template<class Archive> | ||||||
|  |     void serialize(Archive & ar, const unsigned int file_version) | ||||||
|  |     { | ||||||
|  |         ar & regs.reg_array; | ||||||
|  |         // ar & vs;
 | ||||||
|  |         // ar & gs;
 | ||||||
|  |         // ar & input_default_attributes;
 | ||||||
|  |         ar & proctex; | ||||||
|  |         for (auto i = 0; i < lighting.luts.size(); i++) { | ||||||
|  |             ar & lighting.luts[i]; | ||||||
|  |         } | ||||||
|  |         ar & fog.lut; | ||||||
|  |         ar & cmd_list.addr; | ||||||
|  |         ar & cmd_list.length; | ||||||
|  |         ar & immediate; | ||||||
|  |         // ar & gs_unit;
 | ||||||
|  |         // ar & geometry_pipeline;
 | ||||||
|  |         // ar & primitive_assembler;
 | ||||||
|  |         ar & vs_float_regs_counter; | ||||||
|  |         ar & vs_uniform_write_buffer; | ||||||
|  |         ar & gs_float_regs_counter; | ||||||
|  |         ar & gs_uniform_write_buffer; | ||||||
|  |         ar & default_attr_counter; | ||||||
|  |         ar & default_attr_write_buffer; | ||||||
|  |         boost::serialization::split_member(ar, *this, file_version); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template<class Archive> | ||||||
|  |     void save(Archive & ar, const unsigned int file_version) const | ||||||
|  |     { | ||||||
|  |         ar << static_cast<u32>(cmd_list.current_ptr - cmd_list.head_ptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template<class Archive> | ||||||
|  |     void load(Archive & ar, const unsigned int file_version) | ||||||
|  |     { | ||||||
|  |         u32 offset{}; | ||||||
|  |         ar >> offset; | ||||||
|  |         cmd_list.head_ptr = (u32*)VideoCore::g_memory->GetPhysicalPointer(cmd_list.addr); | ||||||
|  |         cmd_list.current_ptr = cmd_list.head_ptr + offset; | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| extern State g_state; ///< Current Pica state
 | extern State g_state; ///< Current Pica state
 | ||||||
|  |  | ||||||
|  | @ -3,9 +3,11 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include "common/archives.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| #include "video_core/pica.h" | #include "video_core/pica.h" | ||||||
|  | #include "video_core/pica_state.h" | ||||||
| #include "video_core/renderer_base.h" | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/renderer_opengl/gl_vars.h" | #include "video_core/renderer_opengl/gl_vars.h" | ||||||
| #include "video_core/renderer_opengl/renderer_opengl.h" | #include "video_core/renderer_opengl/renderer_opengl.h" | ||||||
|  | @ -85,4 +87,18 @@ u16 GetResolutionScaleFactor() { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Save(std::ostream &stream) | ||||||
|  | { | ||||||
|  |     oarchive oa{stream}; | ||||||
|  |     oa & Pica::g_state; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Load(std::istream &stream) | ||||||
|  | { | ||||||
|  |     iarchive ia{stream}; | ||||||
|  |     ia & Pica::g_state; | ||||||
|  |     // TODO: Flush/reset things
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace VideoCore
 | } // namespace VideoCore
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <iostream> | ||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "core/frontend/emu_window.h" | #include "core/frontend/emu_window.h" | ||||||
|  | @ -61,4 +62,7 @@ void RequestScreenshot(void* data, std::function<void()> callback, | ||||||
| 
 | 
 | ||||||
| u16 GetResolutionScaleFactor(); | u16 GetResolutionScaleFactor(); | ||||||
| 
 | 
 | ||||||
|  | void Save(std::ostream &stream); | ||||||
|  | void Load(std::istream &stream); | ||||||
|  | 
 | ||||||
| } // namespace VideoCore
 | } // namespace VideoCore
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue