Serialize geometry_pipeline

master
Hamish Milne 2019-12-22 15:53:04 +07:00 committed by zhupengfei
parent acc89b2251
commit c284192a87
6 changed files with 144 additions and 13 deletions

@ -11,7 +11,7 @@
✔ GPU regs @done(19-08-13 15:41) ✔ GPU regs @done(19-08-13 15:41)
✔ LCD regs @done(19-08-13 15:41) ✔ LCD regs @done(19-08-13 15:41)
☐ Video core @started(19-08-13 16:43) ☐ Video core @started(19-08-13 16:43)
☐ Geometry pipeline ✔ Geometry pipeline @done(19-12-22 15:52)
✔ PICA state @done(19-08-13 15:41) ✔ PICA state @done(19-08-13 15:41)
☐ Primitive assembly ☐ Primitive assembly
✔ Shader @done(19-08-13 16:03) ✔ Shader @done(19-08-13 16:03)
@ -35,9 +35,11 @@
✔ Server session @done(19-08-13 16:44) ✔ Server session @done(19-08-13 16:44)
✔ Session @done(19-08-13 16:44) ✔ Session @done(19-08-13 16:44)
☐ Shared memory ☐ Shared memory
☐ Shared page @started(19-08-13 16:44) ✘ Shared page @started(19-08-13 16:44) @cancelled(19-12-22 11:19)
Not needed right now as shared_page is read-only and derived from other data
☐ SVC ☐ SVC
☐ Thread @started(19-08-13 16:45) ☐ Thread @started(19-08-13 16:45)
This requires refactoring wakeup_callback to be an object ref
✔ Timer @done(19-08-13 16:45) ✔ Timer @done(19-08-13 16:45)
☐ VM Manager @started(19-08-13 16:46) ☐ VM Manager @started(19-08-13 16:46)
✔ Wait object @done(19-08-13 16:46) ✔ Wait object @done(19-08-13 16:46)

2
externals/boost vendored

@ -1 +1 @@
Subproject commit f4850c2975a0d977b7479664b8d4a6f03300a042 Subproject commit 55725b7796c7faa0a4af869e412d0410bd47612d

@ -119,7 +119,8 @@ void KernelSystem::serialize(Archive& ar, const unsigned int file_version)
ar & current_process; ar & current_process;
ar & *thread_manager.get(); ar & *thread_manager.get();
ar & *config_mem_handler.get(); ar & *config_mem_handler.get();
ar & *shared_page_handler.get(); // Shared page data is read-only at the moment, so doesn't need serializing
//ar & *shared_page_handler.get();
} }
SERIALIZE_IMPL(KernelSystem) SERIALIZE_IMPL(KernelSystem)

@ -2,6 +2,10 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include "common/archives.h"
#include "video_core/geometry_pipeline.h" #include "video_core/geometry_pipeline.h"
#include "video_core/pica_state.h" #include "video_core/pica_state.h"
#include "video_core/regs.h" #include "video_core/regs.h"
@ -30,6 +34,13 @@ public:
* @return if the buffer is full and the geometry shader should be invoked * @return if the buffer is full and the geometry shader should be invoked
*/ */
virtual bool SubmitVertex(const Shader::AttributeBuffer& input) = 0; virtual bool SubmitVertex(const Shader::AttributeBuffer& input) = 0;
private:
template <class Archive>
void serialize(Archive& ar, const unsigned int file_version)
{
}
friend class boost::serialization::access;
}; };
// In the Point mode, vertex attributes are sent to the input registers in the geometry shader unit. // In the Point mode, vertex attributes are sent to the input registers in the geometry shader unit.
@ -40,7 +51,7 @@ public:
// TODO: what happens when the input size is not divisible by the output size? // TODO: what happens when the input size is not divisible by the output size?
class GeometryPipeline_Point : public GeometryPipelineBackend { class GeometryPipeline_Point : public GeometryPipelineBackend {
public: public:
GeometryPipeline_Point(const Regs& regs, Shader::GSUnitState& unit) : regs(regs), unit(unit) { GeometryPipeline_Point() : regs(g_state.regs), unit(g_state.gs_unit) {
ASSERT(regs.pipeline.variable_primitive == 0); ASSERT(regs.pipeline.variable_primitive == 0);
ASSERT(regs.gs.input_to_uniform == 0); ASSERT(regs.gs.input_to_uniform == 0);
vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1; vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1;
@ -79,6 +90,39 @@ private:
Common::Vec4<float24>* buffer_cur; Common::Vec4<float24>* buffer_cur;
Common::Vec4<float24>* buffer_end; Common::Vec4<float24>* buffer_end;
unsigned int vs_output_num; unsigned int vs_output_num;
template <typename Class, class Archive>
static void serialize_common(Class* self, Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<GeometryPipelineBackend>(*self);
ar & self->attribute_buffer;
ar & self->vs_output_num;
}
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
serialize_common(this, ar, version);
auto buffer_idx = static_cast<u32>(buffer_cur - attribute_buffer.attr);
auto buffer_size = static_cast<u32>(buffer_end - attribute_buffer.attr);
ar << buffer_idx;
ar << buffer_size;
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
serialize_common(this, ar, version);
u32 buffer_idx, buffer_size;
ar >> buffer_idx;
ar >> buffer_size;
buffer_cur = attribute_buffer.attr + buffer_idx;
buffer_end = attribute_buffer.attr + buffer_size;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
friend class boost::serialization::access;
}; };
// In VariablePrimitive mode, vertex attributes are buffered into the uniform registers in the // In VariablePrimitive mode, vertex attributes are buffered into the uniform registers in the
@ -86,8 +130,8 @@ private:
// value in the batch. This mode is usually used for subdivision. // value in the batch. This mode is usually used for subdivision.
class GeometryPipeline_VariablePrimitive : public GeometryPipelineBackend { class GeometryPipeline_VariablePrimitive : public GeometryPipelineBackend {
public: public:
GeometryPipeline_VariablePrimitive(const Regs& regs, Shader::ShaderSetup& setup) GeometryPipeline_VariablePrimitive()
: regs(regs), setup(setup) { : regs(g_state.regs), setup(g_state.gs) {
ASSERT(regs.pipeline.variable_primitive == 1); ASSERT(regs.pipeline.variable_primitive == 1);
ASSERT(regs.gs.input_to_uniform == 1); ASSERT(regs.gs.input_to_uniform == 1);
vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1; vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1;
@ -144,6 +188,37 @@ private:
unsigned int total_vertex_num; unsigned int total_vertex_num;
Common::Vec4<float24>* buffer_cur; Common::Vec4<float24>* buffer_cur;
unsigned int vs_output_num; unsigned int vs_output_num;
template <typename Class, class Archive>
static void serialize_common(Class* self, Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<GeometryPipelineBackend>(*self);
ar & self->need_index;
ar & self->main_vertex_num;
ar & self->total_vertex_num;
ar & self->vs_output_num;
}
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
serialize_common(this, ar, version);
auto buffer_idx = static_cast<u32>(buffer_cur - setup.uniforms.f);
ar << buffer_idx;
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
serialize_common(this, ar, version);
u32 buffer_idx;
ar >> buffer_idx;
buffer_cur = setup.uniforms.f + buffer_idx;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
friend class boost::serialization::access;
}; };
// In FixedPrimitive mode, vertex attributes are buffered into the uniform registers in the geometry // In FixedPrimitive mode, vertex attributes are buffered into the uniform registers in the geometry
@ -151,8 +226,8 @@ private:
// particle system. // particle system.
class GeometryPipeline_FixedPrimitive : public GeometryPipelineBackend { class GeometryPipeline_FixedPrimitive : public GeometryPipelineBackend {
public: public:
GeometryPipeline_FixedPrimitive(const Regs& regs, Shader::ShaderSetup& setup) GeometryPipeline_FixedPrimitive()
: regs(regs), setup(setup) { : regs(g_state.regs), setup(g_state.gs) {
ASSERT(regs.pipeline.variable_primitive == 0); ASSERT(regs.pipeline.variable_primitive == 0);
ASSERT(regs.gs.input_to_uniform == 1); ASSERT(regs.gs.input_to_uniform == 1);
vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1; vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1;
@ -190,6 +265,42 @@ private:
Common::Vec4<float24>* buffer_cur; Common::Vec4<float24>* buffer_cur;
Common::Vec4<float24>* buffer_end; Common::Vec4<float24>* buffer_end;
unsigned int vs_output_num; unsigned int vs_output_num;
template <typename Class, class Archive>
static void serialize_common(Class* self, Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<GeometryPipelineBackend>(*self);
ar & self->vs_output_num;
}
template<class Archive>
void save(Archive & ar, const unsigned int version) const
{
serialize_common(this, ar, version);
auto buffer_offset = static_cast<u32>(buffer_begin - setup.uniforms.f);
auto buffer_idx = static_cast<u32>(buffer_cur - setup.uniforms.f);
auto buffer_size = static_cast<u32>(buffer_end - setup.uniforms.f);
ar << buffer_offset;
ar << buffer_idx;
ar << buffer_size;
}
template<class Archive>
void load(Archive & ar, const unsigned int version)
{
serialize_common(this, ar, version);
u32 buffer_offset, buffer_idx, buffer_size;
ar >> buffer_offset;
ar >> buffer_idx;
ar >> buffer_size;
buffer_begin = setup.uniforms.f + buffer_offset;
buffer_cur = setup.uniforms.f + buffer_idx;
buffer_end = setup.uniforms.f + buffer_size;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
friend class boost::serialization::access;
}; };
GeometryPipeline::GeometryPipeline(State& state) : state(state) {} GeometryPipeline::GeometryPipeline(State& state) : state(state) {}
@ -231,13 +342,13 @@ void GeometryPipeline::Reconfigure() {
switch (state.regs.pipeline.gs_config.mode) { switch (state.regs.pipeline.gs_config.mode) {
case PipelineRegs::GSMode::Point: case PipelineRegs::GSMode::Point:
backend = std::make_unique<GeometryPipeline_Point>(state.regs, state.gs_unit); backend = std::make_unique<GeometryPipeline_Point>();
break; break;
case PipelineRegs::GSMode::VariablePrimitive: case PipelineRegs::GSMode::VariablePrimitive:
backend = std::make_unique<GeometryPipeline_VariablePrimitive>(state.regs, state.gs); backend = std::make_unique<GeometryPipeline_VariablePrimitive>();
break; break;
case PipelineRegs::GSMode::FixedPrimitive: case PipelineRegs::GSMode::FixedPrimitive:
backend = std::make_unique<GeometryPipeline_FixedPrimitive>(state.regs, state.gs); backend = std::make_unique<GeometryPipeline_FixedPrimitive>();
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -271,4 +382,16 @@ void GeometryPipeline::SubmitVertex(const Shader::AttributeBuffer& input) {
} }
} }
template <class Archive>
void GeometryPipeline::serialize(Archive& ar, const unsigned int version) {
// vertex_handler and shader_engine are always set to the same value
ar & backend;
}
} // namespace Pica } // namespace Pica
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Pica::GeometryPipelineBackend)
SERIALIZE_EXPORT_IMPL(Pica::GeometryPipeline_Point)
SERIALIZE_EXPORT_IMPL(Pica::GeometryPipeline_VariablePrimitive)
SERIALIZE_EXPORT_IMPL(Pica::GeometryPipeline_FixedPrimitive)
SERIALIZE_IMPL(Pica::GeometryPipeline)

@ -45,5 +45,10 @@ private:
Shader::ShaderEngine* shader_engine; Shader::ShaderEngine* shader_engine;
std::unique_ptr<GeometryPipelineBackend> backend; std::unique_ptr<GeometryPipelineBackend> backend;
State& state; State& state;
template <class Archive>
void serialize(Archive& ar, const unsigned int version);
friend class boost::serialization::access;
}; };
} // namespace Pica } // namespace Pica

@ -227,7 +227,7 @@ private:
ar & cmd_list.length; ar & cmd_list.length;
ar & immediate; ar & immediate;
ar & gs_unit; ar & gs_unit;
// ar & geometry_pipeline; ar & geometry_pipeline;
// ar & primitive_assembler; // ar & primitive_assembler;
ar & vs_float_regs_counter; ar & vs_float_regs_counter;
ar & vs_uniform_write_buffer; ar & vs_uniform_write_buffer;