16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-20 07:59:18 +02:00

Tune EU7 PACK streaming with v10 CHNK sub-chunks and worker read cache

Chunk PACK sections at bake time and decode them incrementally at runtime
to cut apply hitches during fast camera flight; cache parsed section headers
per worker thread to avoid reopening and reparsing on every sub-chunk read.
This commit is contained in:
maj00r
2026-06-14 19:49:24 +02:00
parent 8c069ec5f2
commit 56d72fb25e
9 changed files with 336 additions and 23 deletions

View File

@@ -101,6 +101,7 @@ struct PackSectionJob {
int column { 0 };
std::size_t section_idx { 0 };
int priority { 0 };
std::uint32_t next_chunk { 0 };
};
struct PackSectionReady {
@@ -110,6 +111,7 @@ struct PackSectionReady {
std::unique_ptr<std::vector<Eu7Model>> models;
std::vector<std::string> unique_meshes;
bool failed { false };
bool section_final { true };
std::size_t apply_offset { 0 };
std::size_t texture_warm_offset { 0 };
std::size_t umes_cold_offset { 0 };
@@ -820,7 +822,7 @@ apply_pending_chunk(
if( batch.failed ) {
fail_section( batch.section_idx, batch.row, batch.column );
}
else {
else if( batch.section_final ) {
finalize_section( batch );
}
release_pending_buffer();
@@ -832,7 +834,9 @@ apply_pending_chunk(
auto const total { batch.models->size() };
auto const offset { g_stream.pending_apply_offset };
if( offset >= total ) {
finalize_section( batch );
if( batch.section_final ) {
finalize_section( batch );
}
release_pending_buffer();
applied_work = true;
continue;
@@ -983,7 +987,9 @@ apply_pending_chunk(
++chunks_done;
if( g_stream.pending_apply_offset >= total ) {
finalize_section( batch );
if( batch.section_final ) {
finalize_section( batch );
}
release_pending_buffer();
continue;
}
@@ -1115,12 +1121,17 @@ worker_loop( std::stop_token const stop_token ) {
std::unique_ptr<std::vector<Eu7Model>> models;
std::vector<std::string> unique_meshes;
std::uint32_t chunk_count { 1 };
{
PackBenchTimer const read_timer { &Eu7PackBench::worker_read_pack_ms };
auto section { read_pack_section_load( module, job.row, job.column ) };
unique_meshes = std::move( section.unique_meshes );
if( false == section.models.empty() ) {
models = std::make_unique<std::vector<Eu7Model>>( std::move( section.models ) );
auto const chunk {
read_pack_section_chunk_load(
module, job.row, job.column, job.next_chunk ) };
chunk_count = chunk.chunk_count;
unique_meshes = std::move( chunk.unique_meshes );
if( false == chunk.models.empty() ) {
models = std::make_unique<std::vector<Eu7Model>>(
std::move( chunk.models ) );
}
}
@@ -1131,11 +1142,13 @@ worker_loop( std::stop_token const stop_token ) {
result.models = std::move( models );
result.unique_meshes = std::move( unique_meshes );
result.failed = result.models == nullptr;
result.section_final = job.next_chunk + 1 >= chunk_count;
if( result.failed ) {
ErrorLog(
"EU7 PACK: pusty odczyt sekcji " + std::to_string( job.row ) + "," +
std::to_string( job.column ) + " (PIDX model_count=" +
std::to_string( job.column ) + " chunk=" +
std::to_string( job.next_chunk ) + " (PIDX model_count=" +
std::to_string( entry->model_count ) + ")" );
enqueue_failed_section( job );
continue;
@@ -1151,7 +1164,20 @@ worker_loop( std::stop_token const stop_token ) {
g_stream.ready.data.push_back( std::move( result ) );
}
pack_bench_inc( &Eu7PackBench::worker_sections_done );
pack_bench_inc( &Eu7PackBench::worker_chunks_decoded );
if( result.section_final ) {
pack_bench_inc( &Eu7PackBench::worker_sections_done );
}
if( job.next_chunk + 1 < chunk_count ) {
PackSectionJob continue_job { job };
continue_job.next_chunk = job.next_chunk + 1;
{
std::lock_guard<std::mutex> lock { g_stream.jobs.mutex };
g_stream.jobs.data.push_front( continue_job );
}
g_stream.work_cv.notify_one();
}
}
catch( std::exception const &ex ) {
ErrorLog(
@@ -1168,6 +1194,7 @@ stop_workers() {
g_stream.work_cv.notify_all();
g_stream.workers.clear();
g_stream.worker_exit = false;
reset_pack_section_read_cache();
{
std::lock_guard<std::mutex> lock { g_stream.jobs.mutex };
@@ -1581,7 +1608,7 @@ try_dequeue_ready_batch() {
if( it->failed ) {
fail_section( it->section_idx, it->row, it->column );
}
else {
else if( it->section_final ) {
finalize_section( *it );
}
it = g_stream.ready.data.erase( it );
@@ -1672,7 +1699,7 @@ try_dequeue_ready_batch() {
if( batch.failed ) {
fail_section( batch.section_idx, batch.row, batch.column );
}
else {
else if( batch.section_final ) {
finalize_section( batch );
}
return false;