video_core serialization
This commit is contained in:
parent
ee2cae2093
commit
6f00976ab5
|
@ -1,11 +1,14 @@
|
|||
#include "boost/archive/binary_iarchive.hpp"
|
||||
#include "boost/archive/binary_oarchive.hpp"
|
||||
|
||||
#define SERIALIZE_IMPL(A) template void A::serialize<boost::archive::binary_iarchive>( \
|
||||
boost::archive::binary_iarchive & ar, \
|
||||
using iarchive = boost::archive::binary_iarchive;
|
||||
using oarchive = boost::archive::binary_oarchive;
|
||||
|
||||
#define SERIALIZE_IMPL(A) template void A::serialize<iarchive>( \
|
||||
iarchive & ar, \
|
||||
const unsigned int file_version \
|
||||
); \
|
||||
template void A::serialize<boost::archive::binary_oarchive>( \
|
||||
boost::archive::binary_oarchive & ar, \
|
||||
template void A::serialize<oarchive>( \
|
||||
oarchive & ar, \
|
||||
const unsigned int file_version \
|
||||
);
|
||||
|
|
|
@ -397,22 +397,28 @@ void System::Reset() {
|
|||
template<class Archive>
|
||||
void System::serialize(Archive & ar, const unsigned int file_version)
|
||||
{
|
||||
ar & memory;
|
||||
ar & GPU::g_regs;
|
||||
ar & LCD::g_regs;
|
||||
ar & dsp_core->GetDspMemory();
|
||||
ar & memory;
|
||||
}
|
||||
|
||||
void System::Save(std::ostream &stream) const
|
||||
{
|
||||
boost::archive::binary_oarchive oa{stream};
|
||||
{
|
||||
oarchive oa{stream};
|
||||
oa & *this;
|
||||
}
|
||||
VideoCore::Save(stream);
|
||||
}
|
||||
|
||||
void System::Load(std::istream &stream)
|
||||
{
|
||||
boost::archive::binary_iarchive ia{stream};
|
||||
{
|
||||
iarchive ia{stream};
|
||||
ia & *this;
|
||||
}
|
||||
VideoCore::Load(stream);
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -472,14 +472,7 @@ inline void Write(u32 addr, const T data) {
|
|||
if (config.trigger & 1) {
|
||||
MICROPROFILE_SCOPE(GPU_CmdlistProcessing);
|
||||
|
||||
u32* buffer = (u32*)g_memory->GetPhysicalPointer(config.GetPhysicalAddress());
|
||||
|
||||
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);
|
||||
Pica::CommandProcessor::ProcessCommandList(config.GetPhysicalAddress(), config.size);
|
||||
|
||||
g_regs.command_processor_config.trigger = 0;
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ endif()
|
|||
create_target_directory_groups(video_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)
|
||||
target_link_libraries(video_core PUBLIC xbyak)
|
||||
|
|
|
@ -640,8 +640,17 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
|
|||
reinterpret_cast<void*>(&id));
|
||||
}
|
||||
|
||||
void ProcessCommandList(const u32* list, u32 size) {
|
||||
g_state.cmd_list.head_ptr = g_state.cmd_list.current_ptr = list;
|
||||
void ProcessCommandList(PAddr list, u32 size) {
|
||||
|
||||
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);
|
||||
|
||||
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");
|
||||
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
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "boost/serialization/split_member.hpp"
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/vector_math.h"
|
||||
|
@ -13,6 +14,18 @@
|
|||
#include "video_core/regs.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 {
|
||||
|
||||
/// Struct used to describe current Pica state
|
||||
|
@ -79,6 +92,18 @@ struct State {
|
|||
std::array<ValueEntry, 128> alpha_map_table;
|
||||
std::array<ColorEntry, 256> color_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;
|
||||
|
||||
struct Lighting {
|
||||
|
@ -101,6 +126,12 @@ struct State {
|
|||
float diff = static_cast<float>(difference) / 2047.f;
|
||||
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;
|
||||
|
@ -126,8 +157,11 @@ struct State {
|
|||
std::array<LutEntry, 128> lut;
|
||||
} fog;
|
||||
|
||||
#undef SERIALIZE_RAW
|
||||
|
||||
/// Current Pica command list
|
||||
struct {
|
||||
PAddr addr; // This exists only for serialization
|
||||
const u32* head_ptr;
|
||||
const u32* current_ptr;
|
||||
u32 length;
|
||||
|
@ -141,6 +175,17 @@ struct State {
|
|||
u32 current_attribute = 0;
|
||||
// Indicates the immediate mode just started and the geometry pipeline needs to reconfigure
|
||||
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;
|
||||
|
||||
// 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;
|
||||
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
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#include <memory>
|
||||
#include "common/archives.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/settings.h"
|
||||
#include "video_core/pica.h"
|
||||
#include "video_core/pica_state.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/renderer_opengl/gl_vars.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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include "core/frontend/emu_window.h"
|
||||
|
@ -61,4 +62,7 @@ void RequestScreenshot(void* data, std::function<void()> callback,
|
|||
|
||||
u16 GetResolutionScaleFactor();
|
||||
|
||||
void Save(std::ostream &stream);
|
||||
void Load(std::istream &stream);
|
||||
|
||||
} // namespace VideoCore
|
||||
|
|
Reference in New Issue