Make map generator as much threaded as possible (not much benefit with current generator because of small generator chunk size (a single MapBlock))

This commit is contained in:
Perttu Ahola 2011-11-26 15:53:52 +02:00
parent 769cc9879f
commit b2ccbdffc1
3 changed files with 88 additions and 105 deletions

@ -1331,7 +1331,7 @@ minetest.register_on_respawnplayer(function(player)
end) end)
minetest.register_on_generated(function(minp, maxp) minetest.register_on_generated(function(minp, maxp)
--print("on_generated: minp="..dump(minp).." maxp="..dump(maxp)) print("on_generated: minp="..dump(minp).." maxp="..dump(maxp))
--cp = {x=(minp.x+maxp.x)/2, y=(minp.y+maxp.y)/2, z=(minp.z+maxp.z)/2} --cp = {x=(minp.x+maxp.x)/2, y=(minp.y+maxp.y)/2, z=(minp.z+maxp.z)/2}
--minetest.env:add_node(cp, {name="sand"}) --minetest.env:add_node(cp, {name="sand"})
end) end)

@ -2163,6 +2163,16 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
/*infostream<<"Resulting vmanip:"<<std::endl; /*infostream<<"Resulting vmanip:"<<std::endl;
data->vmanip.print(infostream);*/ data->vmanip.print(infostream);*/
// Make sure affected blocks are loaded
for(s16 x=-1; x<=1; x++)
for(s16 z=-1; z<=1; z++)
for(s16 y=-1; y<=1; y++)
{
v3s16 p(blockpos.X+x, blockpos.Y+y, blockpos.Z+z);
// Load from disk if not already in memory
emergeBlock(p, false);
}
/* /*
Blit generated stuff to map Blit generated stuff to map
NOTE: blitBackAll adds nearly everything to changed_blocks NOTE: blitBackAll adds nearly everything to changed_blocks

@ -44,6 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h" #include "nodedef.h"
#include "tooldef.h" #include "tooldef.h"
#include "craftdef.h" #include "craftdef.h"
#include "mapgen.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -143,12 +144,7 @@ void * EmergeThread::Thread()
/* /*
Do not generate over-limit Do not generate over-limit
*/ */
if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE if(blockpos_over_limit(p))
|| p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
continue; continue;
//infostream<<"EmergeThread::Thread(): running"<<std::endl; //infostream<<"EmergeThread::Thread(): running"<<std::endl;
@ -192,128 +188,105 @@ void * EmergeThread::Thread()
ServerMap &map = ((ServerMap&)m_server->m_env->getMap()); ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
//core::map<v3s16, MapBlock*> changed_blocks;
//core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
MapBlock *block = NULL; MapBlock *block = NULL;
bool got_block = true; bool got_block = true;
core::map<v3s16, MapBlock*> modified_blocks; core::map<v3s16, MapBlock*> modified_blocks;
/* /*
Fetch block from map or generate a single block Try to fetch block from memory or disk.
If not found and asked to generate, initialize generator.
*/ */
bool started_generate = false;
mapgen::BlockMakeData data;
{ {
JMutexAutoLock envlock(m_server->m_env_mutex); JMutexAutoLock envlock(m_server->m_env_mutex);
// Load sector if it isn't loaded // Load sector if it isn't loaded
if(map.getSectorNoGenerateNoEx(p2d) == NULL) if(map.getSectorNoGenerateNoEx(p2d) == NULL)
//map.loadSectorFull(p2d);
map.loadSectorMeta(p2d); map.loadSectorMeta(p2d);
// Attempt to load block
block = map.getBlockNoCreateNoEx(p); block = map.getBlockNoCreateNoEx(p);
if(!block || block->isDummy() || !block->isGenerated()) if(!block || block->isDummy() || !block->isGenerated())
{ {
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
infostream<<"EmergeThread: not in memory, loading"<<std::endl; infostream<<"EmergeThread: not in memory, "
<<"attempting to load from disk"<<std::endl;
// Get, load or create sector
/*ServerMapSector *sector =
(ServerMapSector*)map.createSector(p2d);*/
// Load/generate block
/*block = map.emergeBlock(p, sector, changed_blocks,
lighting_invalidated_blocks);*/
block = map.loadBlock(p); block = map.loadBlock(p);
}
if(only_from_disk == false) // If could not load and allowed to generate, start generation
{ // inside this same envlock
if(block == NULL || block->isGenerated() == false) if(only_from_disk == false &&
{ (block == NULL || block->isGenerated() == false)){
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
infostream<<"EmergeThread: generating"<<std::endl; infostream<<"EmergeThread: generating"<<std::endl;
block = map.generateBlock(p, modified_blocks); started_generate = true;
v3s16 minp = block->getPos()*MAP_BLOCKSIZE; map.initBlockMake(&data, p);
v3s16 maxp = minp + v3s16(1,1,1)*(MAP_BLOCKSIZE-1); }
scriptapi_environment_on_generated(m_server->m_lua, }
minp, maxp);
} /*
} If generator was initialized, generate now when envlock is free.
*/
if(started_generate)
{
{
ScopeProfiler sp(g_profiler, "EmergeThread: mapgen::make_block",
SPT_AVG);
TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data);
if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output
}
{
// Lock environment again to access the map
JMutexAutoLock envlock(m_server->m_env_mutex);
ScopeProfiler sp(g_profiler, "EmergeThread: after "
"mapgen::make_block (envlock)", SPT_AVG);
// Blit data back on map, update lighting, add mobs and
// whatever this does
map.finishBlockMake(&data, modified_blocks);
// Get central block
block = map.getBlockNoCreateNoEx(p);
/*
Do some post-generate stuff
*/
v3s16 minp = block->getPos()*MAP_BLOCKSIZE;
v3s16 maxp = minp + v3s16(1,1,1)*(MAP_BLOCKSIZE-1);
scriptapi_environment_on_generated(m_server->m_lua,
minp, maxp);
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
infostream<<"EmergeThread: ended up with: " infostream<<"EmergeThread: ended up with: "
<<analyze_block(block)<<std::endl; <<analyze_block(block)<<std::endl;
if(block == NULL) /*
{ Ignore map edit events, they will not need to be
got_block = false; sent to anybody because the block hasn't been sent
} to anybody
else */
{ MapEditEventIgnorer ign(&m_server->m_ignore_map_edit_events);
/*
Ignore map edit events, they will not need to be
sent to anybody because the block hasn't been sent
to anybody
*/
MapEditEventIgnorer ign(&m_server->m_ignore_map_edit_events);
// Activate objects and stuff // Activate objects and stuff
m_server->m_env->activateBlock(block, 3600); m_server->m_env->activateBlock(block, 3600);
}
} }
else
{
/*if(block->getLightingExpired()){
lighting_invalidated_blocks[block->getPos()] = block;
}*/
}
// TODO: Some additional checking and lighting updating,
// see emergeBlock
} }
{//envlock if(block == NULL)
JMutexAutoLock envlock(m_server->m_env_mutex); got_block = false;
if(got_block)
{
/*
Collect a list of blocks that have been modified in
addition to the fetched one.
*/
#if 0
if(lighting_invalidated_blocks.size() > 0)
{
/*infostream<<"lighting "<<lighting_invalidated_blocks.size()
<<" blocks"<<std::endl;*/
// 50-100ms for single block generation
//TimeTaker timer("** EmergeThread updateLighting");
// Update lighting without locking the environment mutex,
// add modified blocks to changed blocks
map.updateLighting(lighting_invalidated_blocks, modified_blocks);
}
// Add all from changed_blocks to modified_blocks
for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator();
i.atEnd() == false; i++)
{
MapBlock *block = i.getNode()->getValue();
modified_blocks.insert(block->getPos(), block);
}
#endif
}
// If we got no block, there should be no invalidated blocks
else
{
//assert(lighting_invalidated_blocks.size() == 0);
}
}//envlock
/* /*
Set sent status of modified blocks on clients Set sent status of modified blocks on clients