From 4feccaa64af02a7061b60fb17dcedca1e3e3269e Mon Sep 17 00:00:00 2001 From: tycho Date: Sat, 30 May 2015 00:18:52 +0100 Subject: Clean up Spawn Prepare Made cSpawnPrepare execute on the same thread since it is a syncronous operation, and most of the code happens on the lighting thread. Also moved cSpawnPrepare into its own file --- src/SpawnPrepare.cpp | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/SpawnPrepare.cpp (limited to 'src/SpawnPrepare.cpp') diff --git a/src/SpawnPrepare.cpp b/src/SpawnPrepare.cpp new file mode 100644 index 000000000..80d2c52a1 --- /dev/null +++ b/src/SpawnPrepare.cpp @@ -0,0 +1,105 @@ + +#include "Globals.h" + +#include "SpawnPrepare.h" +#include "World.h" + + + + + + + +cSpawnPrepare::cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx): + m_World(a_World), + m_SpawnChunkX(a_SpawnChunkX), + m_SpawnChunkZ(a_SpawnChunkZ), + m_PrepareDistance(a_PrepareDistance), + m_NextIdx(a_FirstIdx), + m_MaxIdx(a_PrepareDistance * a_PrepareDistance), + m_NumPrepared(0), + m_LastReportTime(std::chrono::steady_clock::now()), + m_LastReportChunkCount(0) +{ +} + + + + + + + +void cSpawnPrepare::PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance) +{ + + // Queue the initial chunks: + int MaxIdx = a_PrepareDistance * a_PrepareDistance; + int maxQueue = std::min(MaxIdx - 1, 100); // Number of chunks to queue at once + cSpawnPrepare prep(a_World, a_SpawnChunkX, a_SpawnChunkZ, a_PrepareDistance, maxQueue); + for (int i = 0; i < maxQueue; i++) + { + int chunkX, chunkZ; + prep.DecodeChunkCoords(i, chunkX, chunkZ); + a_World.PrepareChunk(chunkX, chunkZ, &prep); + } // for i + + // Wait for the lighting thread to prepare everything. Event is set in the Call() callback: + prep.m_EvtFinished.Wait(); +} + + + + + +void cSpawnPrepare::DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ) +{ + // A zigzag pattern from the top to bottom, each row alternating between forward-x and backward-x: + int z = a_Idx / m_PrepareDistance; + int x = a_Idx % m_PrepareDistance; + if ((z & 1) == 0) + { + // Reverse every second row: + x = m_PrepareDistance - 1 - x; + } + a_ChunkZ = m_SpawnChunkZ + z - m_PrepareDistance / 2; + a_ChunkX = m_SpawnChunkX + x - m_PrepareDistance / 2; +} + + + + + +void cSpawnPrepare::Call(int a_ChunkX, int a_ChunkZ) +{ + // Check if this was the last chunk: + m_NumPrepared += 1; + if (m_NumPrepared >= m_MaxIdx) + { + m_EvtFinished.Set(); + // Must return here, because "this" may have gotten deleted by the previous line + return; + } + + // Queue another chunk, if appropriate: + if (m_NextIdx < m_MaxIdx) + { + int chunkX, chunkZ; + DecodeChunkCoords(m_NextIdx, chunkX, chunkZ); + m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, this); + m_NextIdx += 1; + } + + // Report progress every 1 second: + auto Now = std::chrono::steady_clock::now(); + if (Now - m_LastReportTime > std::chrono::seconds(1)) + { + float PercentDone = static_cast(m_NumPrepared * 100) / m_MaxIdx; + float ChunkSpeed = static_cast((m_NumPrepared - m_LastReportChunkCount) * 1000) / std::chrono::duration_cast(Now - m_LastReportTime).count(); + LOG("Preparing spawn (%s): %.02f%% (%d/%d; %.02f chunks / sec)", + m_World.GetName().c_str(), PercentDone, m_NumPrepared, m_MaxIdx, ChunkSpeed + ); + m_LastReportTime = Now; + m_LastReportChunkCount = m_NumPrepared; + } +} + -- cgit v1.2.3 From 06a74e45e247a2d23c6b5a238a3c1b9b17b6c341 Mon Sep 17 00:00:00 2001 From: tycho Date: Sat, 30 May 2015 11:11:17 +0100 Subject: Made cLightingThread own its callbacks --- src/SpawnPrepare.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'src/SpawnPrepare.cpp') diff --git a/src/SpawnPrepare.cpp b/src/SpawnPrepare.cpp index 80d2c52a1..74dcb3ecd 100644 --- a/src/SpawnPrepare.cpp +++ b/src/SpawnPrepare.cpp @@ -8,6 +8,26 @@ +class cSpawnPrepareCallback : + public cChunkCoordCallback +{ +public: + cSpawnPrepareCallback(cSpawnPrepare & a_SpawnPrepare) : + m_SpawnPrepare(a_SpawnPrepare) + { + } +protected: + + cSpawnPrepare & m_SpawnPrepare; + + virtual void Call(int a_ChunkX, int a_ChunkZ) override + { + m_SpawnPrepare.PreparedChunkCallback(a_ChunkX, a_ChunkZ); + } +}; + + + cSpawnPrepare::cSpawnPrepare(cWorld & a_World, int a_SpawnChunkX, int a_SpawnChunkZ, int a_PrepareDistance, int a_FirstIdx): @@ -40,7 +60,7 @@ void cSpawnPrepare::PrepareChunks(cWorld & a_World, int a_SpawnChunkX, int a_Spa { int chunkX, chunkZ; prep.DecodeChunkCoords(i, chunkX, chunkZ); - a_World.PrepareChunk(chunkX, chunkZ, &prep); + a_World.PrepareChunk(chunkX, chunkZ, cpp14::make_unique(prep)); } // for i // Wait for the lighting thread to prepare everything. Event is set in the Call() callback: @@ -69,7 +89,7 @@ void cSpawnPrepare::DecodeChunkCoords(int a_Idx, int & a_ChunkX, int & a_ChunkZ) -void cSpawnPrepare::Call(int a_ChunkX, int a_ChunkZ) +void cSpawnPrepare::PreparedChunkCallback(int a_ChunkX, int a_ChunkZ) { // Check if this was the last chunk: m_NumPrepared += 1; @@ -85,7 +105,7 @@ void cSpawnPrepare::Call(int a_ChunkX, int a_ChunkZ) { int chunkX, chunkZ; DecodeChunkCoords(m_NextIdx, chunkX, chunkZ); - m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, this); + m_World.GetLightingThread().QueueChunk(chunkX, chunkZ, cpp14::make_unique(*this)); m_NextIdx += 1; } -- cgit v1.2.3