builtin/voxelworld: WIP: Optimize
This commit is contained in:
parent
24e660b1af
commit
1ef9b870cd
@ -26,6 +26,7 @@
|
|||||||
#include <Geometry.h>
|
#include <Geometry.h>
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using interface::Event;
|
using interface::Event;
|
||||||
namespace magic = Urho3D;
|
namespace magic = Urho3D;
|
||||||
@ -131,6 +132,7 @@ struct Section
|
|||||||
pv::Region contained_chunks;// Position and size in chunks
|
pv::Region contained_chunks;// Position and size in chunks
|
||||||
// Static voxel nodes (each contains one chunk); Initialized to 0.
|
// Static voxel nodes (each contains one chunk); Initialized to 0.
|
||||||
sp_<pv::RawVolume<int32_t>> node_ids;
|
sp_<pv::RawVolume<int32_t>> node_ids;
|
||||||
|
size_t num_chunks = 0;
|
||||||
|
|
||||||
// Chunk write journals (push_back(), pop_front()) (z*h*w + y*w + x)
|
// Chunk write journals (push_back(), pop_front()) (z*h*w + y*w + x)
|
||||||
sv_<std::deque<JournalEntry>> write_journals;
|
sv_<std::deque<JournalEntry>> write_journals;
|
||||||
@ -149,11 +151,11 @@ struct Section
|
|||||||
section_p(section_p),
|
section_p(section_p),
|
||||||
chunk_size(chunk_size),
|
chunk_size(chunk_size),
|
||||||
contained_chunks(contained_chunks),
|
contained_chunks(contained_chunks),
|
||||||
node_ids(new pv::RawVolume<int32_t>(contained_chunks))
|
node_ids(new pv::RawVolume<int32_t>(contained_chunks)),
|
||||||
{
|
num_chunks(contained_chunks.getWidthInVoxels() *
|
||||||
size_t num_chunks = contained_chunks.getWidthInVoxels() *
|
|
||||||
contained_chunks.getHeightInVoxels() *
|
contained_chunks.getHeightInVoxels() *
|
||||||
contained_chunks.getDepthInVoxels();
|
contained_chunks.getDepthInVoxels())
|
||||||
|
{
|
||||||
write_journals.resize(num_chunks);
|
write_journals.resize(num_chunks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,14 +165,15 @@ struct Section
|
|||||||
|
|
||||||
size_t Section::get_chunk_i(const pv::Vector3DInt32 &chunk_p) // global chunk_p
|
size_t Section::get_chunk_i(const pv::Vector3DInt32 &chunk_p) // global chunk_p
|
||||||
{
|
{
|
||||||
if(!contained_chunks.containsPoint(chunk_p))
|
auto &lc = contained_chunks.getLowerCorner();
|
||||||
throw Exception(ss_()+"get_chunk_i: Section "+cs(section_p)+
|
|
||||||
" does not contain chunk"+cs(chunk_p));
|
|
||||||
auto lc = contained_chunks.getLowerCorner();
|
|
||||||
pv::Vector3DInt32 local_p = chunk_p - lc;
|
pv::Vector3DInt32 local_p = chunk_p - lc;
|
||||||
int32_t w = contained_chunks.getWidthInVoxels();
|
int32_t w = contained_chunks.getWidthInVoxels();
|
||||||
int32_t h = contained_chunks.getHeightInVoxels();
|
int32_t h = contained_chunks.getHeightInVoxels();
|
||||||
return (local_p.getZ() * h * w + local_p.getY() * w + local_p.getX());
|
size_t i = local_p.getZ() * h * w + local_p.getY() * w + local_p.getX();
|
||||||
|
if(i >= num_chunks)
|
||||||
|
throw Exception(ss_()+"get_chunk_i: Section "+cs(section_p)+
|
||||||
|
" does not contain chunk"+cs(chunk_p));
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
pv::Vector3DInt32 Section::get_chunk_p(size_t chunk_i)
|
pv::Vector3DInt32 Section::get_chunk_p(size_t chunk_i)
|
||||||
@ -193,10 +196,11 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||||||
sp_<interface::VoxelRegistry> m_voxel_reg;
|
sp_<interface::VoxelRegistry> m_voxel_reg;
|
||||||
sp_<interface::BlockRegistry> m_block_reg;
|
sp_<interface::BlockRegistry> m_block_reg;
|
||||||
|
|
||||||
// One node holds one chunk of voxels (eg. 32x32x32)
|
|
||||||
pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(16, 16, 16);
|
pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(16, 16, 16);
|
||||||
// The world is loaded and unloaded by sections (eg. 4x4x4)
|
|
||||||
pv::Vector3DInt16 m_section_size_chunks = pv::Vector3DInt16(2, 2, 2);
|
pv::Vector3DInt16 m_section_size_chunks = pv::Vector3DInt16(2, 2, 2);
|
||||||
|
// These are suitable for running under valgrind
|
||||||
|
//pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(8, 8, 8);
|
||||||
|
//pv::Vector3DInt16 m_section_size_chunks = pv::Vector3DInt16(2, 2, 2);
|
||||||
|
|
||||||
// TODO: Use these when replication filtering works properly
|
// TODO: Use these when replication filtering works properly
|
||||||
// One node holds one chunk of voxels (eg. 32x32x32)
|
// One node holds one chunk of voxels (eg. 32x32x32)
|
||||||
@ -207,10 +211,11 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||||||
// Sections (this(y,z)=sector, sector(x)=section)
|
// Sections (this(y,z)=sector, sector(x)=section)
|
||||||
sm_<pv::Vector<2, int16_t>, sm_<int16_t, Section>> m_sections;
|
sm_<pv::Vector<2, int16_t>, sm_<int16_t, Section>> m_sections;
|
||||||
// Cache of last used sections (add to end, remove from beginning)
|
// Cache of last used sections (add to end, remove from beginning)
|
||||||
//std::deque<Section*> m_last_used_sections;
|
std::deque<Section*> m_last_used_sections;
|
||||||
|
|
||||||
// Set of sections that have stuff in their journals
|
// Set of sections that have stuff in their journals
|
||||||
std::unordered_set<pv::Vector3DInt16> m_section_journals_dirty;
|
// (as a sorted array in descending order)
|
||||||
|
std::vector<Section*> m_section_journals_dirty;
|
||||||
|
|
||||||
Module(interface::Server *server):
|
Module(interface::Server *server):
|
||||||
interface::Module("voxelworld"),
|
interface::Module("voxelworld"),
|
||||||
@ -407,8 +412,15 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||||||
packet.sender, PV3I_PARAMS(section_p));
|
packet.sender, PV3I_PARAMS(section_p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get section if exists
|
||||||
Section* get_section(const pv::Vector3DInt16 §ion_p)
|
Section* get_section(const pv::Vector3DInt16 §ion_p)
|
||||||
{
|
{
|
||||||
|
// Check cache
|
||||||
|
for(Section *section : m_last_used_sections){
|
||||||
|
if(section->section_p == section_p)
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
// Not in cache
|
||||||
pv::Vector<2, int16_t> p_yz(section_p.getY(), section_p.getZ());
|
pv::Vector<2, int16_t> p_yz(section_p.getY(), section_p.getZ());
|
||||||
auto sector_it = m_sections.find(p_yz);
|
auto sector_it = m_sections.find(p_yz);
|
||||||
if(sector_it == m_sections.end())
|
if(sector_it == m_sections.end())
|
||||||
@ -418,9 +430,14 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||||||
if(section_it == sector.end())
|
if(section_it == sector.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
Section §ion = section_it->second;
|
Section §ion = section_it->second;
|
||||||
|
// Add to cache and return
|
||||||
|
m_last_used_sections.push_back(§ion);
|
||||||
|
if(m_last_used_sections.size() > 2) // 2 is maybe optimal-ish
|
||||||
|
m_last_used_sections.pop_front();
|
||||||
return §ion;
|
return §ion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a section; allocate it if it doesn't exist yet
|
||||||
Section& force_get_section(const pv::Vector3DInt16 §ion_p)
|
Section& force_get_section(const pv::Vector3DInt16 §ion_p)
|
||||||
{
|
{
|
||||||
pv::Vector<2, int16_t> p_yz(section_p.getY(), section_p.getZ());
|
pv::Vector<2, int16_t> p_yz(section_p.getY(), section_p.getZ());
|
||||||
@ -674,7 +691,13 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||||||
// Append to journal
|
// Append to journal
|
||||||
size_t chunk_i = section->get_chunk_i(chunk_p);
|
size_t chunk_i = section->get_chunk_i(chunk_p);
|
||||||
section->write_journals[chunk_i].push_back(JournalEntry(v, p));
|
section->write_journals[chunk_i].push_back(JournalEntry(v, p));
|
||||||
m_section_journals_dirty.insert(section_p);
|
|
||||||
|
// Set journal dirty flag
|
||||||
|
auto dirty_it = std::lower_bound(m_section_journals_dirty.begin(),
|
||||||
|
m_section_journals_dirty.end(), section,
|
||||||
|
std::greater<Section*>()); // position in descending order
|
||||||
|
if(dirty_it == m_section_journals_dirty.end() || *dirty_it != section)
|
||||||
|
m_section_journals_dirty.insert(dirty_it, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
void commit_chunk_journal(Section *section, size_t chunk_i)
|
void commit_chunk_journal(Section *section, size_t chunk_i)
|
||||||
@ -731,13 +754,7 @@ struct Module: public interface::Module, public voxelworld::Interface
|
|||||||
{
|
{
|
||||||
log_v(MODULE, "commit(): %zu section journals dirty",
|
log_v(MODULE, "commit(): %zu section journals dirty",
|
||||||
m_section_journals_dirty.size());
|
m_section_journals_dirty.size());
|
||||||
for(const pv::Vector3DInt16 §ion_p : m_section_journals_dirty){
|
for(Section *section : m_section_journals_dirty){
|
||||||
Section *section = get_section(section_p);
|
|
||||||
if(!section){
|
|
||||||
log_w(MODULE, "commit(): Section " PV3I_FORMAT " not found "
|
|
||||||
"for committing journal", PV3I_PARAMS(section_p));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for(size_t i = 0; i < section->write_journals.size(); i++){
|
for(size_t i = 0; i < section->write_journals.size(); i++){
|
||||||
commit_chunk_journal(section, i);
|
commit_chunk_journal(section, i);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user