mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 01:59:19 +02:00
Skip pure-visual leaf includes in the infrastructure pass
On a million-instance scenery (tomaszewo) the infra pass was spending ~24s reopening pure-visual leaf twins (grass.incb etc.) just to skip their content -- ~200k cParser constructions, because every flora include reopens the same leaf. Twin header now flags whether a file has any infrastructure node or include (format bumped to v10). A pure-visual leaf (flora .incb: triangles + transform directives only) has it clear, so the infra pass skips opening it: the first open of each file caches the verdict, later opens are dropped before construction. Result on tomaszewo: infra 55s -> 31s, getToken 1.06M -> 89k. Also adds a load profiler (per-type build time, dispatch time, getToken count) behind WriteLog so the next bottleneck is measured, not guessed (it's now the 25s of decorative vehicle media loading).
This commit is contained in:
@@ -160,6 +160,7 @@ scenery_binary_writer::add_number( double Value ) {
|
||||
|
||||
void
|
||||
scenery_binary_writer::add_include( std::vector<std::string> const &Fileexpr, std::vector<std::string> const &Params ) {
|
||||
m_has_include = true; // file references other files -> the infra pass must still process it
|
||||
auto &out = sink();
|
||||
write_varint( out, TAG_INCLUDE );
|
||||
write_varint( out, Fileexpr.size() );
|
||||
@@ -183,6 +184,7 @@ scenery_binary_writer::end_node( bool Visual, bool Haspos, double X, double Y, d
|
||||
m_innode = false;
|
||||
auto const body = m_nodebuf.str();
|
||||
write_varint( m_entries, TAG_NODE );
|
||||
if( false == Visual ) { m_has_infra = true; } // infrastructure node -> infra pass must process it
|
||||
auto const cls =
|
||||
( false == Visual ) ? NODECLASS_INFRA :
|
||||
( Haspos ) ? NODECLASS_VISUAL_POS :
|
||||
@@ -206,7 +208,9 @@ scenery_binary_writer::write( std::ostream &Output, scenery_file_kind Kind ) con
|
||||
// header: magic + kind + flags
|
||||
sn_utils::ls_uint32( Output, SCENERYBINARY_MAGIC );
|
||||
sn_utils::s_uint8( Output, static_cast<std::uint8_t>( Kind ) );
|
||||
sn_utils::ls_uint32( Output, 0 ); // flags, reserved
|
||||
// flags bit0: infra-relevant (has an infrastructure node or an include). a pure-visual leaf
|
||||
// has it clear, so the infrastructure pass skips opening it entirely.
|
||||
sn_utils::ls_uint32( Output, ( m_has_infra || m_has_include ) ? 1u : 0u );
|
||||
|
||||
// string table: count, then each string as varint(length) + raw bytes (so the
|
||||
// reader can take views into the buffer without scanning for terminators)
|
||||
@@ -240,7 +244,7 @@ scenery_binary_reader::open( std::string_view Buffer ) {
|
||||
return false;
|
||||
}
|
||||
m_kind = static_cast<scenery_file_kind>( static_cast<std::uint8_t>( *cursor++ ) );
|
||||
read_u32le( cursor, end ); // flags, reserved
|
||||
m_infra_relevant = ( ( read_u32le( cursor, end ) & 1u ) != 0u ); // flags bit0
|
||||
|
||||
// string table: views into the buffer (no copies)
|
||||
auto tablesize = read_varint( cursor, end );
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace scene {
|
||||
// in the visual pass, swallowed the following endorigin -> the origin stack accumulated
|
||||
// and flung terrain/models across the map. bumping invalidates those bad twins.
|
||||
// bumping the version invalidates older twins so they are recompiled rather than misread.
|
||||
constexpr std::uint32_t SCENERYBINARY_MAGIC { MAKE_ID4( 'e', 'u', '7', 9 ) };
|
||||
constexpr std::uint32_t SCENERYBINARY_MAGIC { MAKE_ID4( 'e', 'u', '7', 10 ) };
|
||||
|
||||
// which entries a reader serves in a given load pass; nodes outside the requested class
|
||||
// are skipped (directives/includes are always served, to keep transform/group state)
|
||||
@@ -139,6 +139,8 @@ private:
|
||||
std::ostringstream m_nodebuf; // current node's entries (buffered)
|
||||
bool m_innode { false }; // currently between begin/end_node
|
||||
std::size_t m_count { 0 }; // number of entries
|
||||
bool m_has_infra { false }; // emitted any infrastructure node
|
||||
bool m_has_include { false }; // emitted any include directive
|
||||
};
|
||||
|
||||
// parses a binary twin held in a memory buffer and streams its entries on demand.
|
||||
@@ -151,6 +153,11 @@ public:
|
||||
bool open( std::string_view Buffer );
|
||||
|
||||
scenery_file_kind kind() const { return m_kind; }
|
||||
// true if this file has any infrastructure node or include directive. a pure-visual leaf
|
||||
// (e.g. a flora .incb: triangles + transform directives only) returns false, so the
|
||||
// infrastructure pass can skip opening it entirely instead of traversing it to drop its
|
||||
// visual content -- which on a million-instance scenery was ~200k wasted reopens.
|
||||
bool infra_relevant() const { return m_infra_relevant; }
|
||||
// selects which nodes are served vs skipped (default: all). may be changed between
|
||||
// reads (e.g. to drive separate eager/visual passes over a re-opened twin).
|
||||
void set_pass( scenery_load_pass Pass ) { m_pass = Pass; }
|
||||
@@ -190,6 +197,7 @@ private:
|
||||
double m_noderange { -1.0 }; // range_max of the current node (v9 model marker)
|
||||
std::size_t m_nodeoffset { 0 }; // byte offset of the current node's marker (for seek_node)
|
||||
bool m_nodehaspos { false }; // whether the current node's marker carried a position
|
||||
bool m_infra_relevant { true }; // header flag: has infrastructure node or include
|
||||
std::ptrdiff_t m_size { 0 }; // entry section byte length
|
||||
scenery_load_pass m_pass { scenery_load_pass::all };
|
||||
scenery_file_kind m_kind { scenery_file_kind::scn };
|
||||
|
||||
Reference in New Issue
Block a user