From c284192a87ae7fe2ec4ff0e3b5e86863a44a445c Mon Sep 17 00:00:00 2001 From: Hamish Milne Date: Sun, 22 Dec 2019 15:53:04 +0000 Subject: [PATCH] Serialize geometry_pipeline --- TODO | 6 +- externals/boost | 2 +- src/core/hle/kernel/kernel.cpp | 3 +- src/video_core/geometry_pipeline.cpp | 139 +++++++++++++++++++++++++-- src/video_core/geometry_pipeline.h | 5 + src/video_core/pica_state.h | 2 +- 6 files changed, 144 insertions(+), 13 deletions(-) diff --git a/TODO b/TODO index 3f15f3fb5..840caba1b 100644 --- a/TODO +++ b/TODO @@ -11,7 +11,7 @@ ✔ GPU regs @done(19-08-13 15:41) ✔ LCD regs @done(19-08-13 15:41) ☐ 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) ☐ Primitive assembly ✔ Shader @done(19-08-13 16:03) @@ -35,9 +35,11 @@ ✔ Server session @done(19-08-13 16:44) ✔ Session @done(19-08-13 16:44) ☐ 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 ☐ Thread @started(19-08-13 16:45) + This requires refactoring wakeup_callback to be an object ref ✔ Timer @done(19-08-13 16:45) ☐ VM Manager @started(19-08-13 16:46) ✔ Wait object @done(19-08-13 16:46) diff --git a/externals/boost b/externals/boost index f4850c297..55725b779 160000 --- a/externals/boost +++ b/externals/boost @@ -1 +1 @@ -Subproject commit f4850c2975a0d977b7479664b8d4a6f03300a042 +Subproject commit 55725b7796c7faa0a4af869e412d0410bd47612d diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 32d76d0d3..2dd0a34bf 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -119,7 +119,8 @@ void KernelSystem::serialize(Archive& ar, const unsigned int file_version) ar & current_process; ar & *thread_manager.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) diff --git a/src/video_core/geometry_pipeline.cpp b/src/video_core/geometry_pipeline.cpp index 3a24b71c9..44a2fd6da 100644 --- a/src/video_core/geometry_pipeline.cpp +++ b/src/video_core/geometry_pipeline.cpp @@ -2,6 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include +#include "common/archives.h" #include "video_core/geometry_pipeline.h" #include "video_core/pica_state.h" #include "video_core/regs.h" @@ -30,6 +34,13 @@ public: * @return if the buffer is full and the geometry shader should be invoked */ virtual bool SubmitVertex(const Shader::AttributeBuffer& input) = 0; + +private: + template + 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. @@ -40,7 +51,7 @@ public: // TODO: what happens when the input size is not divisible by the output size? class GeometryPipeline_Point : public GeometryPipelineBackend { 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.gs.input_to_uniform == 0); vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1; @@ -79,6 +90,39 @@ private: Common::Vec4* buffer_cur; Common::Vec4* buffer_end; unsigned int vs_output_num; + + template + static void serialize_common(Class* self, Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object(*self); + ar & self->attribute_buffer; + ar & self->vs_output_num; + } + + template + void save(Archive & ar, const unsigned int version) const + { + serialize_common(this, ar, version); + auto buffer_idx = static_cast(buffer_cur - attribute_buffer.attr); + auto buffer_size = static_cast(buffer_end - attribute_buffer.attr); + ar << buffer_idx; + ar << buffer_size; + } + + template + 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 @@ -86,8 +130,8 @@ private: // value in the batch. This mode is usually used for subdivision. class GeometryPipeline_VariablePrimitive : public GeometryPipelineBackend { public: - GeometryPipeline_VariablePrimitive(const Regs& regs, Shader::ShaderSetup& setup) - : regs(regs), setup(setup) { + GeometryPipeline_VariablePrimitive() + : regs(g_state.regs), setup(g_state.gs) { ASSERT(regs.pipeline.variable_primitive == 1); ASSERT(regs.gs.input_to_uniform == 1); vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1; @@ -144,6 +188,37 @@ private: unsigned int total_vertex_num; Common::Vec4* buffer_cur; unsigned int vs_output_num; + + template + static void serialize_common(Class* self, Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object(*self); + ar & self->need_index; + ar & self->main_vertex_num; + ar & self->total_vertex_num; + ar & self->vs_output_num; + } + + template + void save(Archive & ar, const unsigned int version) const + { + serialize_common(this, ar, version); + auto buffer_idx = static_cast(buffer_cur - setup.uniforms.f); + ar << buffer_idx; + } + + template + 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 @@ -151,8 +226,8 @@ private: // particle system. class GeometryPipeline_FixedPrimitive : public GeometryPipelineBackend { public: - GeometryPipeline_FixedPrimitive(const Regs& regs, Shader::ShaderSetup& setup) - : regs(regs), setup(setup) { + GeometryPipeline_FixedPrimitive() + : regs(g_state.regs), setup(g_state.gs) { ASSERT(regs.pipeline.variable_primitive == 0); ASSERT(regs.gs.input_to_uniform == 1); vs_output_num = regs.pipeline.vs_outmap_total_minus_1_a + 1; @@ -190,6 +265,42 @@ private: Common::Vec4* buffer_cur; Common::Vec4* buffer_end; unsigned int vs_output_num; + + template + static void serialize_common(Class* self, Archive& ar, const unsigned int version) + { + ar & boost::serialization::base_object(*self); + ar & self->vs_output_num; + } + + template + void save(Archive & ar, const unsigned int version) const + { + serialize_common(this, ar, version); + auto buffer_offset = static_cast(buffer_begin - setup.uniforms.f); + auto buffer_idx = static_cast(buffer_cur - setup.uniforms.f); + auto buffer_size = static_cast(buffer_end - setup.uniforms.f); + ar << buffer_offset; + ar << buffer_idx; + ar << buffer_size; + } + + template + 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) {} @@ -231,13 +342,13 @@ void GeometryPipeline::Reconfigure() { switch (state.regs.pipeline.gs_config.mode) { case PipelineRegs::GSMode::Point: - backend = std::make_unique(state.regs, state.gs_unit); + backend = std::make_unique(); break; case PipelineRegs::GSMode::VariablePrimitive: - backend = std::make_unique(state.regs, state.gs); + backend = std::make_unique(); break; case PipelineRegs::GSMode::FixedPrimitive: - backend = std::make_unique(state.regs, state.gs); + backend = std::make_unique(); break; default: UNREACHABLE(); @@ -271,4 +382,16 @@ void GeometryPipeline::SubmitVertex(const Shader::AttributeBuffer& input) { } } +template +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 + +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) diff --git a/src/video_core/geometry_pipeline.h b/src/video_core/geometry_pipeline.h index 91fdd3192..1ca2d00c4 100644 --- a/src/video_core/geometry_pipeline.h +++ b/src/video_core/geometry_pipeline.h @@ -45,5 +45,10 @@ private: Shader::ShaderEngine* shader_engine; std::unique_ptr backend; State& state; + + template + void serialize(Archive& ar, const unsigned int version); + + friend class boost::serialization::access; }; } // namespace Pica diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h index ba9f8235e..d7ae04c1b 100644 --- a/src/video_core/pica_state.h +++ b/src/video_core/pica_state.h @@ -227,7 +227,7 @@ private: ar & cmd_list.length; ar & immediate; ar & gs_unit; - // ar & geometry_pipeline; + ar & geometry_pipeline; // ar & primitive_assembler; ar & vs_float_regs_counter; ar & vs_uniform_write_buffer;