diff --git a/src/client/client.cpp b/src/client/client.cpp index 0f9ee8a6b..b350e1cc5 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -563,7 +563,8 @@ void Client::step(float dtime) std::vector minimap_mapblocks; bool do_mapper_update = true; - MapSector *sector = m_env.getMap().emergeSector(v2s16(r.p.X, r.p.Z)); + ClientMap &map = m_env.getClientMap(); + MapSector *sector = map.emergeSector(v2s16(r.p.X, r.p.Z)); MapBlock *block = sector->getBlockNoCreateNoEx(r.p.Y); @@ -575,6 +576,8 @@ void Client::step(float dtime) if (block) { // Delete the old mesh + if (block->mesh) + map.invalidateMapBlockMesh(block->mesh); delete block->mesh; block->mesh = nullptr; block->solid_sides = r.solid_sides; @@ -589,10 +592,9 @@ void Client::step(float dtime) if (r.mesh->getMesh(l)->getMeshBufferCount() != 0) is_empty = false; - // <- invalidate here? - if (is_empty) + if (is_empty) { delete r.mesh; - else { + } else { // Replace with the new mesh block->mesh = r.mesh; if (r.urgent) diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index 0a746fa7d..0a5a3f963 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -841,12 +841,12 @@ static u32 transformBuffersToDrawOrder( driver->removeHardwareBuffer(buf->getIndexBuffer()); } + // TODO: explain and document std::string kkk; std::sort(to_merge.begin(), to_merge.end(), [] (const auto &l, const auto &r) { - return l.second < r.second; + return static_cast(l.second) < static_cast(r.second); }); for (auto &it : to_merge) { - // TODO?: big assumptions here kkk.append(reinterpret_cast(&it.second), sizeof(it.second)); } @@ -1092,6 +1092,55 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) g_profiler->avg(prefix + "material swaps [#]", material_swaps); } +void ClientMap::invalidateMapBlockMesh(MapBlockMesh *mesh) +{ + ScopeProfiler sp(g_profiler, "CM::invalidateMapBlockMesh", SPT_ADD, PRECISION_MICRO); + + // find all buffers + MeshBufListMaps tmp; + tmp.addFromBlock(v3s16(), mesh, getSceneManager()->getVideoDriver()); + + std::vector to_delete; + void *maxp = 0; + for (auto &it : tmp.maps) { + for (auto &it2 : it) { + for (auto &it3 : it2.second) { + void *const p = it3.second; + to_delete.push_back(p); + maxp = std::max(maxp, p); + } + } + } + + g_profiler->add("CM::invalidateMapBlockMesh to_delete", to_delete.size()); + + if (to_delete.empty()) + return; + + // remove matching cache elements + u32 deleted = 0; + for (auto it = m_dynamic_buffers.begin(); it != m_dynamic_buffers.end(); ) { + const std::string &key = it->first; + assert(key.size() % sizeof(void*) == 0); + for (size_t off = 0; off < key.size(); off += sizeof(void*)) { + void *v; + memcpy(&v, &key[off], sizeof(void*)); + if (v > maxp) // early exit + break; + if (CONTAINS(to_delete, v)) { + it = m_dynamic_buffers.erase(it); + deleted++; + goto continue_outer; + } + } + it++; + continue_outer: + continue; + } + + g_profiler->add("CM::invalidateMapBlockMesh deleted", deleted); +} + static bool getVisibleBrightness(Map *map, const v3f &p0, v3f dir, float step, float step_multiplier, float start_distance, float end_distance, const NodeDefManager *ndef, u32 daylight_factor, float sunlight_min_d, diff --git a/src/client/clientmap.h b/src/client/clientmap.h index dae97b417..b76e513e2 100644 --- a/src/client/clientmap.h +++ b/src/client/clientmap.h @@ -103,6 +103,8 @@ public: void renderPostFx(CameraMode cam_mode); + void invalidateMapBlockMesh(MapBlockMesh *mesh); + // For debug printing void PrintInfo(std::ostream &out) override; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 47dc2ad3f..4851ebf73 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -104,7 +104,7 @@ void set_default_settings() settings->setDefault("sound_extensions_blacklist", ""); settings->setDefault("mesh_generation_interval", "0"); settings->setDefault("mesh_generation_threads", "0"); - settings->setDefault("mesh_buffer_min_vertices", "100"); + settings->setDefault("mesh_buffer_min_vertices", "300"); settings->setDefault("free_move", "false"); settings->setDefault("pitch_move", "false"); settings->setDefault("fast_move", "false");