mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 00:49:19 +02:00
Enable --eu7v2-bake from the main binary: parallel module pool, bounded-RAM spool flush, streaming terrain triangles, flat include/model parsing, and eu7v2 emit/load with optional verify. Large placement .scm files emit lean PLCE records and bake referenced .inc modules separately for reuse. - CLI: --eu7v2-bake, --eu7v2-verify, --eu7v2-mem-limit-gb, --eu7v2-threads, --eu7v2-max-parse; wire max_threads through to the bake parser - eu7v2 v2 records: PLCE placements, runtime emitter/loader, batch verify - Parallel bake pool with session cache; drop heavy-serial parse gate in spool mode; parse concurrency matches thread count - Streaming terrain: batched parallel parse+bake, scan/bake pipeline, shape spool with persistent buffered I/O and flush-before-read - Parallel flat-file streaming for models/includes; pack/model spool for low-memory incremental flush - Optional 50 GB private-bytes guard during headless bake Braniewo_szeroki: 160 modules, verify PASS, ~34s bake (nmt100 ~17s vs ~190s serial baseline). Co-authored-by: Cursor <cursoragent@cursor.com>
352 lines
5.1 KiB
C++
352 lines
5.1 KiB
C++
/*
|
|
|
|
This Source Code Form is subject to the
|
|
|
|
terms of the Mozilla Public License, v.
|
|
|
|
2.0. If a copy of the MPL was not
|
|
|
|
distributed with this file, You can
|
|
|
|
obtain one at
|
|
|
|
http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "scene/eu7/eu7_bake.h"
|
|
|
|
|
|
|
|
#include "scene/eu7/eu7_loader.h"
|
|
|
|
#include "utilities/Globals.h"
|
|
|
|
#include "utilities/Logs.h"
|
|
|
|
#include "utilities/utilities.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <thread>
|
|
|
|
|
|
|
|
#ifdef WITH_EU7_PARSER
|
|
|
|
#include "scene/eu7/eu7_bake_parser.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace scene::eu7 {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
[[nodiscard]] unsigned
|
|
|
|
bake_thread_count() {
|
|
|
|
if( Global.eu7_bake_threads > 0 ) {
|
|
|
|
return static_cast<unsigned>( Global.eu7_bake_threads );
|
|
|
|
}
|
|
|
|
auto const hardware { std::thread::hardware_concurrency() };
|
|
|
|
if( hardware == 0 ) {
|
|
|
|
return 1u;
|
|
|
|
}
|
|
|
|
int percent { Global.eu7_bake_cpu_percent };
|
|
|
|
if( percent < 1 ) { percent = 1; }
|
|
|
|
if( percent > 100 ) { percent = 100; }
|
|
|
|
unsigned const threads {
|
|
|
|
std::max( 1u,
|
|
|
|
static_cast<unsigned>( ( static_cast<unsigned long long>( hardware ) * percent + 50 ) / 100 ) ) };
|
|
|
|
WriteLog(
|
|
|
|
"EU7 bake: auto watki=" + std::to_string( threads ) +
|
|
|
|
" (" + std::to_string( percent ) + "% z " + std::to_string( hardware ) + " rdzeni logicznych)" );
|
|
|
|
return threads;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WITH_EU7_PARSER
|
|
|
|
[[nodiscard]] bool
|
|
|
|
run_scenario_tree_bake(
|
|
|
|
std::string const &text_root,
|
|
|
|
std::string const &eu7_path,
|
|
|
|
Eu7BakeOutcome &outcome ) {
|
|
|
|
WriteLog(
|
|
|
|
"EU7 bake: generowanie modulow z \"" + text_root + "\" (watek=" +
|
|
|
|
std::to_string( bake_thread_count() ) + ")" );
|
|
|
|
|
|
|
|
std::string error;
|
|
|
|
bool bake_ok { false };
|
|
|
|
if( Global.eu7v2_runtime ) {
|
|
|
|
auto const report {
|
|
|
|
bake_parser::bake_scenario_tree_eu7v2( text_root, bake_thread_count(), false ) };
|
|
|
|
bake_ok = report.baked;
|
|
|
|
error = report.error;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bake_ok = bake_parser::bake_scenario_tree( text_root, bake_thread_count(), error );
|
|
|
|
}
|
|
|
|
if( false == bake_ok ) {
|
|
|
|
if( probe_file( eu7_path ) ) {
|
|
|
|
ErrorLog(
|
|
|
|
"EU7 bake nieudany, uzywam istniejacego modulu: " + error );
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "fallback na stary .eu7 po bledzie bake";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
outcome.message = error;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( false == probe_file( eu7_path ) ) {
|
|
|
|
outcome.message = "bake zakonczony, ale brak pliku: " + eu7_path;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.regenerated = true;
|
|
|
|
outcome.message = eu7_path;
|
|
|
|
WriteLog( "EU7 bake: zapisano " + eu7_path );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
bool
|
|
|
|
scenario_needs_eu7_regen( std::string const &scenario_file ) {
|
|
|
|
#ifdef WITH_EU7_PARSER
|
|
|
|
if( false == Global.eu7_auto_bake ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto const resolved { resolve_scenery_path( scenario_file ) };
|
|
|
|
|
|
|
|
if( probe_file( resolved ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( false == is_text_module_extension( resolved ) || false == FileExists( resolved ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false == probe_baked_scenario( scenario_file );
|
|
|
|
#else
|
|
|
|
(void)scenario_file;
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Eu7BakeOutcome
|
|
|
|
ensure_scenario_eu7( std::string const &scenario_file ) {
|
|
|
|
Eu7BakeOutcome outcome;
|
|
|
|
auto const resolved { resolve_scenery_path( scenario_file ) };
|
|
|
|
auto const eu7_path { resolve_scenery_path( binary_path( scenario_file ) ) };
|
|
|
|
|
|
|
|
if( probe_file( resolved ) ) {
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "uzywam .eu7: " + resolved;
|
|
|
|
WriteLog( "EU7: uzywam .eu7: " + resolved );
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef WITH_EU7_PARSER
|
|
|
|
if( false == Global.eu7_auto_bake ) {
|
|
|
|
if( probe_baked_scenario( scenario_file ) ) {
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "eu7_auto_bake wylaczone, uzywam istniejacego .eu7";
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "eu7_auto_bake wylaczone, ladowanie SCM";
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( false == is_text_module_extension( resolved ) ) {
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "nie jest scenariuszem tekstowym";
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
if( false == FileExists( resolved ) ) {
|
|
|
|
outcome.message = "brak pliku scenariusza: " + resolved;
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( probe_baked_scenario( scenario_file ) ) {
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "uzywam istniejacego .eu7: " + eu7_path;
|
|
|
|
WriteLog( "EU7: uzywam .eu7: " + eu7_path );
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
|
|
|
|
run_scenario_tree_bake( resolved, eu7_path, outcome );
|
|
|
|
return outcome;
|
|
|
|
#else
|
|
|
|
if( probe_baked_scenario( scenario_file ) ) {
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "uzywam istniejacego .eu7 (parser niedostepny w buildzie)";
|
|
|
|
return outcome;
|
|
|
|
}
|
|
|
|
outcome.ok = true;
|
|
|
|
outcome.message = "parser niedostepny, ladowanie SCM";
|
|
|
|
return outcome;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace scene::eu7
|