video_core serialization

This commit is contained in:
Hamish Milne 2019-08-07 17:08:52 +01:00 committed by zhupengfei
parent ee2cae2093
commit 6f00976ab5
9 changed files with 142 additions and 21 deletions

View file

@ -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 \
);

View file

@ -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};
oa & *this;
{
oarchive oa{stream};
oa & *this;
}
VideoCore::Save(stream);
}
void System::Load(std::istream &stream)
{
boost::archive::binary_iarchive ia{stream};
ia & *this;
{
iarchive ia{stream};
ia & *this;
}
VideoCore::Load(stream);
}
} // namespace Core

View file

@ -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;
}

View file

@ -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)

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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