@@ -1772,46 +1772,68 @@ void Renderer::EnqueueEntityPreallocationBatch(const std::vector<Entity *> &enti
17721772 pendingEntityPreallocQueued.store (true , std::memory_order_relaxed);
17731773}
17741774
1775+ void Renderer::EnqueueInstanceBufferRecreation (Entity *entity)
1776+ {
1777+ if (!entity)
1778+ return ;
1779+ {
1780+ std::lock_guard<std::mutex> lk (pendingEntityPreallocMutex);
1781+ pendingInstanceBufferRecreations.push_back (entity);
1782+ }
1783+ pendingEntityPreallocQueued.store (true , std::memory_order_relaxed);
1784+ }
1785+
17751786void Renderer::ProcessPendingEntityPreallocations ()
17761787{
17771788 if (!pendingEntityPreallocQueued.load (std::memory_order_relaxed))
17781789 return ;
17791790
1780- std::vector<Entity *> toProcess;
1791+ std::vector<Entity *> toPreallocate;
1792+ std::vector<Entity *> toRecreateInstances;
17811793 {
17821794 std::lock_guard<std::mutex> lk (pendingEntityPreallocMutex);
1783- if (pendingEntityPrealloc.empty ())
1795+ if (pendingEntityPrealloc.empty () && pendingInstanceBufferRecreations. empty () )
17841796 {
17851797 pendingEntityPreallocQueued.store (false , std::memory_order_relaxed);
17861798 return ;
17871799 }
1788- toProcess.swap (pendingEntityPrealloc);
1800+ toPreallocate.swap (pendingEntityPrealloc);
1801+ toRecreateInstances.swap (pendingInstanceBufferRecreations);
17891802 pendingEntityPreallocQueued.store (false , std::memory_order_relaxed);
17901803 }
17911804
1792- // De-dup to avoid repeated work if loader enqueues overlapping batches
1793- std::sort (toProcess .begin (), toProcess .end ());
1794- toProcess .erase (std::unique (toProcess .begin (), toProcess .end ()), toProcess .end ());
1805+ // De-dup preallocations
1806+ std::sort (toPreallocate .begin (), toPreallocate .end ());
1807+ toPreallocate .erase (std::unique (toPreallocate .begin (), toPreallocate .end ()), toPreallocate .end ());
17951808
17961809 std::vector<Entity *> batch;
1797- batch.reserve (toProcess .size ());
1798- for (Entity *e : toProcess )
1810+ batch.reserve (toPreallocate .size ());
1811+ for (Entity *e : toPreallocate )
17991812 {
18001813 if (!e || !e->IsActive ())
18011814 continue ;
1802- // Only preallocate for entities that actually have renderable mesh data
18031815 if (!e->GetComponent <MeshComponent>())
18041816 continue ;
18051817 batch.push_back (e);
18061818 }
1807- if (batch.empty ())
1808- return ;
18091819
1810- // Execute GPU resource creation on the render thread at the safe point.
1811- // Keep failures non-fatal so loading can continue; we'll retry on subsequent frames.
1812- if (!preAllocateEntityResourcesBatch (batch))
1820+ if (!batch.empty ())
1821+ {
1822+ if (!preAllocateEntityResourcesBatch (batch))
1823+ {
1824+ std::cerr << " Warning: batch entity GPU preallocation failed; will retry" << std::endl;
1825+ }
1826+ }
1827+
1828+ // Process instance buffer recreations
1829+ for (Entity *e : toRecreateInstances)
18131830 {
1814- std::cerr << " Warning: batch entity GPU preallocation failed; will retry" << std::endl;
1831+ if (!e || !e->IsActive ())
1832+ continue ;
1833+ if (!recreateInstanceBuffer (e))
1834+ {
1835+ std::cerr << " Warning: failed to recreate instance buffer for entity " << e->GetName () << std::endl;
1836+ }
18151837 }
18161838}
18171839
0 commit comments