Merge branch 'master' into full_load_mode

master
Marc Gilleron 2021-10-13 20:29:58 +01:00
commit 375c68b0de
7 changed files with 15 additions and 11 deletions

View File

@ -56,6 +56,7 @@ Ongoing development - `master`
- `VoxelTerrain`: fixed materials shown under the wrong inspector category
- `VoxelStreamRegionFiles`: fixed errors caused by meta file being sometimes written with wrong depth values
- `VoxelStreamBlockFiles`: fixed warning about channels always shown in the scene tree
- `VoxelStreamSQLite`: fixed blocks above LOD0 being saved at wrong locations, causing them to be reloaded often floating in the air
- Fix some crashes occurring when all PoolVector allocs are in use (Godot 3.x limitation). It will print errors instead, but crashes can still occur inside Godot's code as it's not often checking for this

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -67,13 +67,11 @@ No test framework is used at the moment, instead they just run by either printin
Threads
---------
The module uses several background thread pools to process voxels. The number of threads is currently hardcoded, but it is planned to make it detect CPU concurrency automatically, and expose maximum thread counts in Project Settings.
The module uses several background thread pools to process voxels. The number of threads can be adjusted in Project Settings.
![Schema of threads](images/threads_schema.png)
- A single streaming thread is handling files. If a block of voxels cannot be found, it can pass tasks to one of the generation threads.
- One or more generation threads are used for procedural generation. They can pass tasks to the streaming thread if the option to save generated outputs is enabled.
- One or more meshing threads are used to polygonize voxels into meshes.
There are two pools of threads currently. One pool is actually just one thread dedicated to streaming (files I/O), and another pool uses more threads for every other type of task. This pool can be given many tasks and distributes them to all its threads. So the more threads are available, the quicker large amounts of tasks get done. Tasks are also sorted by priority, so for example updating a mesh near a player will run before generating a voxel block 300 meters away.
Threads are managed in [VoxelServer](api/VoxelServer.md).
@ -99,6 +97,7 @@ For the most part, use `clang-format` and follow Godot conventions.
- Indent with tabs
- Use Clang-format to automate most of these rules (the one included in Godot should do it)
- Constructors and destructors go on top
- Public API goes on top, private stuff goes below
- Bindings go at the bottom. Private wrapper functions can be used to adapt to the script API and are prefixed with `_b_`.
- Avoid long lines. Preferred ruler is 120 characters. Don't fit too many operations on the same line, use locals.

View File

@ -82,7 +82,7 @@ protected:
// Output is blocky, so we can go for just one sample
float h = params.range.xform(height_func(gx, gz));
h -= origin.y;
int ih = int(h);
int ih = int(h) >> lod;
if (ih > 0) {
if (ih > bs.y) {
ih = bs.y;

View File

@ -96,11 +96,12 @@ void VoxelMemoryPool::clear() {
CRASH_COND(ptr == nullptr);
memfree(ptr);
}
memdelete(pool);
}
_pools.clear();
_used_memory = 0;
_total_memory = 0;
_used_blocks;
_used_blocks = 0;
}
void VoxelMemoryPool::debug_print() {

View File

@ -661,7 +661,7 @@ void VoxelStreamSQLite::emerge_blocks(Span<VoxelBlockRequest> p_blocks, Vector<R
Vector<int> blocks_to_load;
for (unsigned int i = 0; i < p_blocks.size(); ++i) {
VoxelBlockRequest &wr = p_blocks[i];
const Vector3i pos = wr.origin_in_voxels >> bs_po2;
const Vector3i pos = wr.origin_in_voxels >> (bs_po2 + wr.lod);
Ref<VoxelBuffer> vb;
if (_cache.load_voxel_block(pos, wr.lod, wr.voxel_buffer)) {
@ -687,10 +687,12 @@ void VoxelStreamSQLite::emerge_blocks(Span<VoxelBlockRequest> p_blocks, Vector<R
const int ri = blocks_to_load[i];
const VoxelBlockRequest &r = p_blocks[ri];
const unsigned int po2 = bs_po2 + r.lod;
BlockLocation loc;
loc.x = r.origin_in_voxels.x >> bs_po2;
loc.y = r.origin_in_voxels.y >> bs_po2;
loc.z = r.origin_in_voxels.z >> bs_po2;
loc.x = r.origin_in_voxels.x >> po2;
loc.y = r.origin_in_voxels.y >> po2;
loc.z = r.origin_in_voxels.z >> po2;
loc.lod = r.lod;
const Result res = con->load_block(loc, _temp_block_data, VoxelStreamSQLiteInternal::VOXELS);
@ -716,7 +718,7 @@ void VoxelStreamSQLite::immerge_blocks(Span<VoxelBlockRequest> p_blocks) {
// First put in cache
for (unsigned int i = 0; i < p_blocks.size(); ++i) {
VoxelBlockRequest &r = p_blocks[i];
const Vector3i pos = r.origin_in_voxels >> bs_po2;
const Vector3i pos = r.origin_in_voxels >> (bs_po2 + r.lod);
if (!BlockLocation::validate(pos, r.lod)) {
ERR_PRINT(String("Block position {0} is outside of supported range").format(varray(pos.to_vec3())));

View File

@ -177,6 +177,7 @@ Array VoxelInstanceLibraryItem::serialize_multimesh_item_properties() const {
}
void VoxelInstanceLibraryItem::deserialize_multimesh_item_properties(Array a) {
ERR_FAIL_COND(a.size() != _mesh_lods.size() + 6);
int ai = 0;
for (unsigned int i = 0; i < _mesh_lods.size(); ++i) {
_mesh_lods[i] = a[ai++];