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_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
|
||||||
|
|
Reference in New Issue