Define smart pointers default allocator in a single place

master
Marc Gilleron 2022-04-10 20:10:33 +01:00
parent 118563d545
commit 0cc3801655
32 changed files with 153 additions and 116 deletions

4
SCsub
View File

@ -74,7 +74,9 @@ env_voxel.Append(CPPDEFINES=[
# Godot 4 includes an official version, which means they would both conflict at linking time.
# To prevent this clash we wrap the entire library within an additional namespace.
# This should be solved either by solving issue #311 or by porting the module to a dynamic library (GDExtension).
"MESHOPTIMIZER_ZYLANN_WRAP_LIBRARY_IN_NAMESPACE"
"MESHOPTIMIZER_ZYLANN_WRAP_LIBRARY_IN_NAMESPACE",
# Tell engine-agnostic code we are using Godot Engine
"ZN_GODOT"
])
if RUN_TESTS:

View File

@ -260,7 +260,7 @@ template <typename Op_T>
class VoxelToolAsyncEdit : public IThreadedTask {
public:
VoxelToolAsyncEdit(Op_T op, std::shared_ptr<VoxelDataLodMap> data) : _op(op), _data(data) {
_tracker = gd_make_shared<AsyncDependencyTracker>(1);
_tracker = make_shared_instance<AsyncDependencyTracker>(1);
}
void run(ThreadedTaskContext ctx) override {

View File

@ -5,6 +5,7 @@
#include "../../storage/voxel_memory_pool.h"
#include "../../streams/vox_data.h"
#include "../../util/macros.h"
#include "../../util/memory.h"
#include "../../util/profiling.h"
#include "vox_import_funcs.h"
@ -128,7 +129,7 @@ void for_each_model_instance(const Data &vox_data, F f) {
struct ModelInstance {
// Model with baked rotation
std::unique_ptr<VoxelBufferInternal> voxels;
UniquePtr<VoxelBufferInternal> voxels;
// Lowest corner position
Vector3i position;
};
@ -162,7 +163,7 @@ void extract_model_instances(const Data &vox_data, std::vector<ModelInstance> &o
// TODO Optimization: implement transformation for VoxelBuffers so we can avoid using a temporary copy.
// Didn't do it yet because VoxelBuffers also have metadata and the `transform_3d_array_zxy` function only works
// on arrays.
std::unique_ptr<VoxelBufferInternal> voxels = std::make_unique<VoxelBufferInternal>();
UniquePtr<VoxelBufferInternal> voxels = make_unique_instance<VoxelBufferInternal>();
voxels->create(dst_size);
voxels->decompress_channel(VoxelBufferInternal::CHANNEL_COLOR);

View File

@ -863,7 +863,7 @@ static bool has_output_type(
VoxelGraphRuntime::CompilationResult VoxelGeneratorGraph::compile() {
const int64_t time_before = Time::get_singleton()->get_ticks_usec();
std::shared_ptr<Runtime> r = std::make_shared<Runtime>();
std::shared_ptr<Runtime> r = make_shared_instance<Runtime>();
VoxelGraphRuntime &runtime = r->runtime;
// Core compilation

View File

@ -34,7 +34,7 @@ void GenerateBlockTask::run(zylann::ThreadedTaskContext ctx) {
const Vector3i origin_in_voxels = (position << lod) * block_size;
if (voxels == nullptr) {
voxels = gd_make_shared<VoxelBufferInternal>();
voxels = make_shared_instance<VoxelBufferInternal>();
voxels->create(block_size, block_size, block_size);
}
@ -51,7 +51,7 @@ void GenerateBlockTask::run(zylann::ThreadedTaskContext ctx) {
ZN_PRINT_VERBOSE(format("Requesting save of generator output for block {} lod {}", position, lod));
// TODO Optimization: `voxels` doesnt actually need to be shared
std::shared_ptr<VoxelBufferInternal> voxels_copy = gd_make_shared<VoxelBufferInternal>();
std::shared_ptr<VoxelBufferInternal> voxels_copy = make_shared_instance<VoxelBufferInternal>();
voxels->duplicate_to(*voxels_copy, true);
// No instances, generators are not designed to produce them at this stage yet.

View File

@ -45,7 +45,7 @@ void LoadBlockDataTask::run(zylann::ThreadedTaskContext ctx) {
const Vector3i origin_in_voxels = (_position << _lod) * _block_size;
ERR_FAIL_COND(_voxels != nullptr);
_voxels = gd_make_shared<VoxelBufferInternal>();
_voxels = make_shared_instance<VoxelBufferInternal>();
_voxels->create(_block_size, _block_size, _block_size);
// TODO We should consider batching this again, but it needs to be done carefully.

View File

@ -1,6 +1,7 @@
#ifndef LOAD_BLOCK_DATA_TASK_H
#define LOAD_BLOCK_DATA_TASK_H
#include "../util/memory.h"
#include "../util/tasks/threaded_task.h"
#include "priority_dependency.h"
#include "streaming_dependency.h"
@ -25,7 +26,7 @@ public:
private:
PriorityDependency _priority_dependency;
std::shared_ptr<VoxelBufferInternal> _voxels;
std::unique_ptr<InstanceBlockData> _instances;
UniquePtr<InstanceBlockData> _instances;
Vector3i _position; // In data blocks of the specified lod
uint32_t _volume_id;
uint8_t _lod;

View File

@ -27,7 +27,7 @@ SaveBlockDataTask::SaveBlockDataTask(uint32_t p_volume_id, Vector3i p_block_pos,
}
SaveBlockDataTask::SaveBlockDataTask(uint32_t p_volume_id, Vector3i p_block_pos, uint8_t p_lod, uint8_t p_block_size,
std::unique_ptr<InstanceBlockData> p_instances, std::shared_ptr<StreamingDependency> p_stream_dependency) :
UniquePtr<InstanceBlockData> p_instances, std::shared_ptr<StreamingDependency> p_stream_dependency) :
_instances(std::move(p_instances)),
_position(p_block_pos),
_volume_id(p_volume_id),

View File

@ -1,6 +1,7 @@
#ifndef SAVE_BLOCK_DATA_TASK_H
#define SAVE_BLOCK_DATA_TASK_H
#include "../util/memory.h"
#include "../util/tasks/threaded_task.h"
#include "streaming_dependency.h"
@ -14,7 +15,7 @@ public:
// For saving instances only
SaveBlockDataTask(uint32_t p_volume_id, Vector3i p_block_pos, uint8_t p_lod, uint8_t p_block_size,
std::unique_ptr<InstanceBlockData> p_instances, std::shared_ptr<StreamingDependency> p_stream_dependency);
UniquePtr<InstanceBlockData> p_instances, std::shared_ptr<StreamingDependency> p_stream_dependency);
~SaveBlockDataTask();
@ -27,7 +28,7 @@ public:
private:
std::shared_ptr<VoxelBufferInternal> _voxels;
std::unique_ptr<InstanceBlockData> _instances;
UniquePtr<InstanceBlockData> _instances;
Vector3i _position; // In data blocks of the specified lod
uint32_t _volume_id;
uint8_t _lod;

View File

@ -101,7 +101,7 @@ VoxelServer::VoxelServer() {
_general_thread_pool.set_batch_count(1);
// Init world
_world.shared_priority_dependency = gd_make_shared<PriorityDependency::ViewersData>();
_world.shared_priority_dependency = make_shared_instance<PriorityDependency::ViewersData>();
ZN_PRINT_VERBOSE(format("Size of LoadBlockDataTask: {}", sizeof(LoadBlockDataTask)));
ZN_PRINT_VERBOSE(format("Size of SaveBlockDataTask: {}", sizeof(SaveBlockDataTask)));
@ -146,7 +146,7 @@ uint32_t VoxelServer::add_volume(VolumeCallbacks callbacks, VolumeType type) {
Volume volume;
volume.type = type;
volume.callbacks = callbacks;
volume.meshing_dependency = gd_make_shared<MeshingDependency>();
volume.meshing_dependency = make_shared_instance<MeshingDependency>();
return _world.volumes.create(volume);
}
@ -174,7 +174,7 @@ void VoxelServer::set_volume_stream(uint32_t volume_id, Ref<VoxelStream> stream)
volume.stream_dependency->valid = false;
}
volume.stream_dependency = gd_make_shared<StreamingDependency>();
volume.stream_dependency = make_shared_instance<StreamingDependency>();
volume.stream_dependency->generator = volume.generator;
volume.stream_dependency->stream = volume.stream;
}
@ -188,7 +188,7 @@ void VoxelServer::set_volume_generator(uint32_t volume_id, Ref<VoxelGenerator> g
volume.stream_dependency->valid = false;
}
volume.stream_dependency = gd_make_shared<StreamingDependency>();
volume.stream_dependency = make_shared_instance<StreamingDependency>();
volume.stream_dependency->generator = volume.generator;
volume.stream_dependency->stream = volume.stream;
@ -196,7 +196,7 @@ void VoxelServer::set_volume_generator(uint32_t volume_id, Ref<VoxelGenerator> g
volume.meshing_dependency->valid = false;
}
volume.meshing_dependency = gd_make_shared<MeshingDependency>();
volume.meshing_dependency = make_shared_instance<MeshingDependency>();
volume.meshing_dependency->mesher = volume.mesher;
volume.meshing_dependency->generator = volume.generator;
}
@ -209,7 +209,7 @@ void VoxelServer::set_volume_mesher(uint32_t volume_id, Ref<VoxelMesher> mesher)
volume.meshing_dependency->valid = false;
}
volume.meshing_dependency = gd_make_shared<MeshingDependency>();
volume.meshing_dependency = make_shared_instance<MeshingDependency>();
volume.meshing_dependency->mesher = volume.mesher;
volume.meshing_dependency->generator = volume.generator;
}
@ -222,7 +222,7 @@ void VoxelServer::set_volume_octree_lod_distance(uint32_t volume_id, float lod_d
void VoxelServer::invalidate_volume_mesh_requests(uint32_t volume_id) {
Volume &volume = _world.volumes.get(volume_id);
volume.meshing_dependency->valid = false;
volume.meshing_dependency = gd_make_shared<MeshingDependency>();
volume.meshing_dependency = make_shared_instance<MeshingDependency>();
volume.meshing_dependency->mesher = volume.mesher;
volume.meshing_dependency->generator = volume.generator;
}
@ -369,7 +369,7 @@ void VoxelServer::request_voxel_block_save(
}
void VoxelServer::request_instance_block_save(
uint32_t volume_id, std::unique_ptr<InstanceBlockData> instances, Vector3i block_pos, int lod) {
uint32_t volume_id, UniquePtr<InstanceBlockData> instances, Vector3i block_pos, int lod) {
const Volume &volume = _world.volumes.get(volume_id);
ERR_FAIL_COND(volume.stream.is_null());
CRASH_COND(volume.stream_dependency == nullptr);
@ -531,7 +531,7 @@ void VoxelServer::process() {
const size_t viewer_count = _world.viewers.count();
if (_world.shared_priority_dependency->viewers.size() != viewer_count) {
// TODO We can avoid the invalidation by using an atomic size or memory barrier?
_world.shared_priority_dependency = gd_make_shared<PriorityDependency::ViewersData>();
_world.shared_priority_dependency = make_shared_instance<PriorityDependency::ViewersData>();
_world.shared_priority_dependency->viewers.resize(viewer_count);
}
size_t i = 0;

View File

@ -47,7 +47,7 @@ public:
Type type;
std::shared_ptr<VoxelBufferInternal> voxels;
std::unique_ptr<InstanceBlockData> instances;
UniquePtr<InstanceBlockData> instances;
Vector3i position;
uint8_t lod;
bool dropped;
@ -123,7 +123,7 @@ public:
void request_voxel_block_save(
uint32_t volume_id, std::shared_ptr<VoxelBufferInternal> voxels, Vector3i block_pos, int lod);
void request_instance_block_save(
uint32_t volume_id, std::unique_ptr<InstanceBlockData> instances, Vector3i block_pos, int lod);
uint32_t volume_id, UniquePtr<InstanceBlockData> instances, Vector3i block_pos, int lod);
void remove_volume(uint32_t volume_id);
bool is_volume_valid(uint32_t volume_id) const;

View File

@ -1,6 +1,6 @@
#include "voxel_buffer_gd.h"
#include "../edition/voxel_tool_buffer.h"
#include "../util/godot/funcs.h"
#include "../util/memory.h"
#include <core/io/image.h>
@ -11,7 +11,7 @@ static thread_local bool s_create_shared = false;
VoxelBuffer::VoxelBuffer() {
if (!s_create_shared) {
_buffer = gd_make_shared<VoxelBufferInternal>();
_buffer = make_shared_instance<VoxelBufferInternal>();
}
}

View File

@ -1,8 +1,8 @@
#include "voxel_data_map.h"
#include "../constants/cube_tables.h"
#include "../generators/voxel_generator.h"
#include "../util/godot/funcs.h"
#include "../util/macros.h"
#include "../util/memory.h"
#include <limits>
@ -61,7 +61,7 @@ int VoxelDataMap::get_voxel(Vector3i pos, unsigned int c) const {
}
VoxelDataBlock *VoxelDataMap::create_default_block(Vector3i bpos) {
std::shared_ptr<VoxelBufferInternal> buffer = gd_make_shared<VoxelBufferInternal>();
std::shared_ptr<VoxelBufferInternal> buffer = make_shared_instance<VoxelBufferInternal>();
buffer->create(_block_size, _block_size, _block_size);
buffer->set_default_values(_default_voxel);
VoxelDataBlock *block = VoxelDataBlock::create(bpos, buffer, _block_size, _lod_index);
@ -397,7 +397,7 @@ void preload_box(VoxelDataLodMap &data, Box3i voxel_box, VoxelGenerator *generat
// Generate
for (unsigned int i = 0; i < todo.size(); ++i) {
Task &task = todo[i];
task.voxels = gd_make_shared<VoxelBufferInternal>();
task.voxels = make_shared_instance<VoxelBufferInternal>();
task.voxels->create(block_size);
// TODO Format?
if (generator != nullptr) {

View File

@ -768,7 +768,7 @@ void VoxelStreamSQLite::load_instance_blocks(Span<VoxelStream::InstancesQueryDat
q.result = RESULT_ERROR;
continue;
}
q.data = std::make_unique<InstanceBlockData>();
q.data = make_unique_instance<InstanceBlockData>();
if (!deserialize_instance_block_data(*q.data, to_span_const(_temp_block_data))) {
ERR_PRINT("Failed to deserialize instance block");
q.result = RESULT_ERROR;
@ -830,7 +830,7 @@ void VoxelStreamSQLite::load_all_blocks(FullLoadingResult &result) {
result_block.lod = location.lod;
if (voxel_data.size() > 0) {
std::shared_ptr<VoxelBufferInternal> voxels = gd_make_shared<VoxelBufferInternal>();
std::shared_ptr<VoxelBufferInternal> voxels = make_shared_instance<VoxelBufferInternal>();
ERR_FAIL_COND(!BlockSerializer::decompress_and_deserialize(voxel_data, *voxels));
result_block.voxels = voxels;
}
@ -841,7 +841,7 @@ void VoxelStreamSQLite::load_all_blocks(FullLoadingResult &result) {
ERR_PRINT("Failed to decompress instance block");
return;
}
result_block.instances_data = std::make_unique<InstanceBlockData>();
result_block.instances_data = make_unique_instance<InstanceBlockData>();
if (!deserialize_instance_block_data(*result_block.instances_data, to_span_const(temp_block_data))) {
ERR_PRINT("Failed to deserialize instance block");
return;

View File

@ -162,8 +162,7 @@ static Basis parse_basis(uint8_t data) {
return b;
}
Error parse_node_common_header(
Node &node, FileAccess &f, const std::unordered_map<int, std::unique_ptr<Node>> &scene_graph) {
Error parse_node_common_header(Node &node, FileAccess &f, const std::unordered_map<int, UniquePtr<Node>> &scene_graph) {
//
const int node_id = f.get_32();
ERR_FAIL_COND_V_MSG(scene_graph.find(node_id) != scene_graph.end(), ERR_INVALID_DATA,
@ -242,7 +241,7 @@ Error Data::_load_from_file(String fpath) {
last_size = magica_to_opengl(size);
} else if (strcmp(chunk_id, "XYZI") == 0) {
std::unique_ptr<Model> model = std::make_unique<Model>();
UniquePtr<Model> model = make_unique_instance<Model>();
model->color_indexes.resize(last_size.x * last_size.y * last_size.z, 0);
model->size = last_size;
@ -276,7 +275,7 @@ Error Data::_load_from_file(String fpath) {
f.get_32();
} else if (strcmp(chunk_id, "nTRN") == 0) {
std::unique_ptr<TransformNode> node_ptr = std::make_unique<TransformNode>();
UniquePtr<TransformNode> node_ptr = make_unique_instance<TransformNode>();
TransformNode &node = *node_ptr;
Error header_err = parse_node_common_header(node, f, _scene_graph);
@ -333,7 +332,7 @@ Error Data::_load_from_file(String fpath) {
_scene_graph[node.id] = std::move(node_ptr);
} else if (strcmp(chunk_id, "nGRP") == 0) {
std::unique_ptr<GroupNode> node_ptr = std::make_unique<GroupNode>();
UniquePtr<GroupNode> node_ptr = make_unique_instance<GroupNode>();
GroupNode &node = *node_ptr;
Error header_err = parse_node_common_header(node, f, _scene_graph);
@ -351,7 +350,7 @@ Error Data::_load_from_file(String fpath) {
_scene_graph[node.id] = std::move(node_ptr);
} else if (strcmp(chunk_id, "nSHP") == 0) {
std::unique_ptr<ShapeNode> node_ptr = std::make_unique<ShapeNode>();
UniquePtr<ShapeNode> node_ptr = make_unique_instance<ShapeNode>();
ShapeNode &node = *node_ptr;
Error header_err = parse_node_common_header(node, f, _scene_graph);
@ -374,7 +373,7 @@ Error Data::_load_from_file(String fpath) {
_scene_graph[node.id] = std::move(node_ptr);
} else if (strcmp(chunk_id, "LAYR") == 0) {
std::unique_ptr<Layer> layer_ptr = std::make_unique<Layer>();
UniquePtr<Layer> layer_ptr = make_unique_instance<Layer>();
Layer &layer = *layer_ptr;
const int layer_id = f.get_32();
@ -407,7 +406,7 @@ Error Data::_load_from_file(String fpath) {
_layers.push_back(std::move(layer_ptr));
} else if (strcmp(chunk_id, "MATL") == 0) {
std::unique_ptr<Material> material_ptr = std::make_unique<Material>();
UniquePtr<Material> material_ptr = make_unique_instance<Material>();
Material &material = *material_ptr;
const int material_id = f.get_32();

View File

@ -4,10 +4,10 @@
#include "../util/fixed_array.h"
#include "../util/math/color8.h"
#include "../util/math/vector3i.h"
#include "../util/memory.h"
#include <core/math/basis.h>
#include <core/string/ustring.h>
#include <memory>
#include <unordered_map>
#include <vector>
@ -128,11 +128,11 @@ public:
private:
Error _load_from_file(String fpath);
std::vector<std::unique_ptr<Model>> _models;
std::vector<std::unique_ptr<Layer>> _layers;
std::unordered_map<int, std::unique_ptr<Node>> _scene_graph;
std::vector<UniquePtr<Model>> _models;
std::vector<UniquePtr<Layer>> _layers;
std::unordered_map<int, UniquePtr<Node>> _scene_graph;
// Material IDs are supposedly tied to palette indices
std::unordered_map<int, std::unique_ptr<Material>> _materials;
std::unordered_map<int, UniquePtr<Material>> _materials;
int _root_node_id = -1;
FixedArray<Color8, 256> _palette;
};

View File

@ -1,9 +1,9 @@
#ifndef VOXEL_STREAM_H
#define VOXEL_STREAM_H
#include "../util/memory.h"
#include "instance_data.h"
#include <core/io/resource.h>
#include <memory>
namespace zylann::voxel {
@ -49,7 +49,7 @@ public:
};
struct InstancesQueryData {
std::unique_ptr<InstanceBlockData> data;
UniquePtr<InstanceBlockData> data;
Vector3i position;
uint8_t lod;
ResultCode result;
@ -80,7 +80,7 @@ public:
struct FullLoadingResult {
struct Block {
std::shared_ptr<VoxelBufferInternal> voxels;
std::unique_ptr<InstanceBlockData> instances_data;
UniquePtr<InstanceBlockData> instances_data;
Vector3i position;
unsigned int lod;
};

View File

@ -50,7 +50,7 @@ void VoxelStreamCache::save_voxel_block(Vector3i position, uint8_t lod_index, Vo
}
bool VoxelStreamCache::load_instance_block(
Vector3i position, uint8_t lod_index, std::unique_ptr<InstanceBlockData> &out_instances) {
Vector3i position, uint8_t lod_index, UniquePtr<InstanceBlockData> &out_instances) {
const Lod &lod = _cache[lod_index];
lod.rw_lock.read_lock();
auto it = lod.blocks.find(position);
@ -68,7 +68,7 @@ bool VoxelStreamCache::load_instance_block(
} else {
// Copying is required since the cache has ownership on its data
out_instances = std::make_unique<InstanceBlockData>();
out_instances = make_unique_instance<InstanceBlockData>();
it->second.instances->copy_to(*out_instances);
}
@ -78,7 +78,7 @@ bool VoxelStreamCache::load_instance_block(
}
void VoxelStreamCache::save_instance_block(
Vector3i position, uint8_t lod_index, std::unique_ptr<InstanceBlockData> instances) {
Vector3i position, uint8_t lod_index, UniquePtr<InstanceBlockData> instances) {
Lod &lod = _cache[lod_index];
RWLockWrite wlock(lod.rw_lock);
auto it = lod.blocks.find(position);

View File

@ -2,8 +2,8 @@
#define VOXEL_STREAM_CACHE_H
#include "../storage/voxel_buffer_internal.h"
#include "../util/memory.h"
#include "instance_data.h"
#include <memory>
#include <unordered_map>
namespace zylann::voxel {
@ -23,7 +23,7 @@ public:
bool voxels_deleted = false;
VoxelBufferInternal voxels;
std::unique_ptr<InstanceBlockData> instances;
UniquePtr<InstanceBlockData> instances;
};
// Copies cached block into provided buffer
@ -33,10 +33,10 @@ public:
void save_voxel_block(Vector3i position, uint8_t lod_index, VoxelBufferInternal &voxels);
// Copies cached data into the provided pointer. A new instance will be made if found.
bool load_instance_block(Vector3i position, uint8_t lod_index, std::unique_ptr<InstanceBlockData> &out_instances);
bool load_instance_block(Vector3i position, uint8_t lod_index, UniquePtr<InstanceBlockData> &out_instances);
// Stores provided block into the cache. The cache will take ownership of the provided data.
void save_instance_block(Vector3i position, uint8_t lod_index, std::unique_ptr<InstanceBlockData> instances);
void save_instance_block(Vector3i position, uint8_t lod_index, UniquePtr<InstanceBlockData> instances);
unsigned int get_indicative_block_count() const;

View File

@ -618,7 +618,7 @@ struct ScheduleSaveAction {
VoxelTerrain::BlockToSave b;
if (with_copy) {
RWLockRead lock(block.get_voxels().get_lock());
b.voxels = gd_make_shared<VoxelBufferInternal>();
b.voxels = make_shared_instance<VoxelBufferInternal>();
block.get_voxels_const().duplicate_to(*b.voxels, true);
} else {
b.voxels = block.get_voxels_shared();

View File

@ -281,7 +281,7 @@ private:
Ref<Material> _materials[VoxelMesherBlocky::MAX_MATERIALS];
GodotUniqueObjectPtr<VoxelDataBlockEnterInfo> _data_block_enter_info_obj;
GodotObjectUniquePtr<VoxelDataBlockEnterInfo> _data_block_enter_info_obj;
VoxelInstancer *_instancer = nullptr;

View File

@ -742,7 +742,7 @@ void VoxelInstancer::remove_block(unsigned int block_index) {
}
void VoxelInstancer::on_data_block_loaded(
Vector3i grid_position, unsigned int lod_index, std::unique_ptr<InstanceBlockData> instances) {
Vector3i grid_position, unsigned int lod_index, UniquePtr<InstanceBlockData> instances) {
ERR_FAIL_COND(lod_index >= _lods.size());
Lod &lod = _lods[lod_index];
lod.loaded_instances_data.insert(std::make_pair(grid_position, std::move(instances)));
@ -1128,7 +1128,7 @@ void VoxelInstancer::save_block(Vector3i data_grid_pos, int lod_index) const {
const Lod &lod = _lods[lod_index];
std::unique_ptr<InstanceBlockData> data = std::make_unique<InstanceBlockData>();
UniquePtr<InstanceBlockData> data = make_unique_instance<InstanceBlockData>();
const int data_block_size = (1 << _parent_data_block_size_po2) << lod_index;
data->position_range = data_block_size;

View File

@ -6,6 +6,7 @@
#include "../../util/fixed_array.h"
#include "../../util/godot/direct_multimesh_instance.h"
#include "../../util/math/box3i.h"
#include "../../util/memory.h"
#include "voxel_instance_generator.h"
#include "voxel_instance_library.h"
#include "voxel_instance_library_multimesh_item.h"
@ -17,7 +18,6 @@
#include <scene/3d/node_3d.h>
//#include <scene/resources/material.h> // Included by node.h lol
#include <limits>
#include <memory>
#include <unordered_map>
#include <vector>
@ -64,8 +64,7 @@ public:
// Event handlers
void on_data_block_loaded(
Vector3i grid_position, unsigned int lod_index, std::unique_ptr<InstanceBlockData> instances);
void on_data_block_loaded(Vector3i grid_position, unsigned int lod_index, UniquePtr<InstanceBlockData> instances);
void on_mesh_block_enter(Vector3i render_grid_position, unsigned int lod_index, Array surface_arrays);
void on_mesh_block_exit(Vector3i render_grid_position, unsigned int lod_index);
void on_area_edited(Box3i p_voxel_box);
@ -196,7 +195,7 @@ private:
// it will get generated instances.
// Keys follows the data block coordinate system.
// Can't use `HashMap` because it lacks move semantics.
std::unordered_map<Vector3i, std::unique_ptr<InstanceBlockData>> loaded_instances_data;
std::unordered_map<Vector3i, UniquePtr<InstanceBlockData>> loaded_instances_data;
FixedArray<MeshLodDistances, VoxelInstanceLibraryMultiMeshItem::MAX_MESH_LODS> mesh_lod_distances;
};

View File

@ -97,7 +97,7 @@ struct ScheduleSaveAction {
//print_line(String("Scheduling save for block {0}").format(varray(block->position.to_vec3())));
VoxelLodTerrainUpdateData::BlockToSave b;
b.voxels = gd_make_shared<VoxelBufferInternal>();
b.voxels = make_shared_instance<VoxelBufferInternal>();
{
RWLockRead lock(block.get_voxels().get_lock());
block.get_voxels_const().duplicate_to(*b.voxels, true);
@ -124,11 +124,11 @@ VoxelLodTerrain::VoxelLodTerrain() {
ZN_PRINT_VERBOSE("Construct VoxelLodTerrain");
_data = gd_make_shared<VoxelDataLodMap>();
_update_data = gd_make_shared<VoxelLodTerrainUpdateData>();
_data = make_shared_instance<VoxelDataLodMap>();
_update_data = make_shared_instance<VoxelLodTerrainUpdateData>();
_update_data->task_is_complete = true;
_streaming_dependency = gd_make_shared<StreamingDependency>();
_meshing_dependency = gd_make_shared<MeshingDependency>();
_streaming_dependency = make_shared_instance<StreamingDependency>();
_meshing_dependency = make_shared_instance<MeshingDependency>();
set_notify_transform(true);
@ -221,7 +221,7 @@ void VoxelLodTerrain::set_stream(Ref<VoxelStream> p_stream) {
_stream = p_stream;
_streaming_dependency->valid = false;
_streaming_dependency = gd_make_shared<StreamingDependency>();
_streaming_dependency = make_shared_instance<StreamingDependency>();
_streaming_dependency->stream = _stream;
_streaming_dependency->generator = _generator;
_streaming_dependency->valid = true;
@ -255,13 +255,13 @@ void VoxelLodTerrain::set_generator(Ref<VoxelGenerator> p_generator) {
_generator = p_generator;
_meshing_dependency->valid = false;
_meshing_dependency = gd_make_shared<MeshingDependency>();
_meshing_dependency = make_shared_instance<MeshingDependency>();
_meshing_dependency->mesher = _mesher;
_meshing_dependency->generator = p_generator;
_meshing_dependency->valid = true;
_streaming_dependency->valid = false;
_streaming_dependency = gd_make_shared<StreamingDependency>();
_streaming_dependency = make_shared_instance<StreamingDependency>();
_streaming_dependency->stream = _stream;
_streaming_dependency->generator = p_generator;
_streaming_dependency->valid = true;
@ -306,7 +306,7 @@ void VoxelLodTerrain::set_mesher(Ref<VoxelMesher> p_mesher) {
_mesher = p_mesher;
_meshing_dependency->valid = false;
_meshing_dependency = gd_make_shared<MeshingDependency>();
_meshing_dependency = make_shared_instance<MeshingDependency>();
_meshing_dependency->mesher = _mesher;
_meshing_dependency->generator = _generator;
_meshing_dependency->valid = true;
@ -590,7 +590,7 @@ bool VoxelLodTerrain::try_set_voxel_without_update(Vector3i pos, unsigned int ch
return false;
}
if (_generator.is_valid()) {
voxels = gd_make_shared<VoxelBufferInternal>();
voxels = make_shared_instance<VoxelBufferInternal>();
voxels->create(Vector3iUtil::create(get_data_block_size()));
VoxelGenerator::VoxelQueryData q{ *voxels, pos, 0 };
_generator->generate_block(q);
@ -828,7 +828,7 @@ void VoxelLodTerrain::reset_maps() {
VoxelLodTerrainUpdateData::State &state = _update_data->state;
// Make a new one, so if threads still reference the old one it will be a different copy
_data = gd_make_shared<VoxelDataLodMap>();
_data = make_shared_instance<VoxelDataLodMap>();
_data->lod_count = lod_count;
for (unsigned int lod_index = 0; lod_index < state.lods.size(); ++lod_index) {

View File

@ -97,7 +97,7 @@ void VoxelLodTerrainUpdateTask::flush_pending_lod_edits(VoxelLodTerrainUpdateDat
if (full_load_mode) {
// TODO Doing this on the main thread can be very demanding and cause a stall.
// We should find a way to make it asynchronous, not need mips, or not edit outside viewers area.
std::shared_ptr<VoxelBufferInternal> voxels = gd_make_shared<VoxelBufferInternal>();
std::shared_ptr<VoxelBufferInternal> voxels = make_shared_instance<VoxelBufferInternal>();
voxels->create(Vector3iUtil::create(data_block_size));
if (generator.is_valid()) {
ZN_PROFILE_SCOPE_NAMED("Generate");
@ -1292,8 +1292,8 @@ static std::shared_ptr<AsyncDependencyTracker> preload_boxes_async(VoxelLodTerra
// it would destroy `next_tasks`.
// This may first run the generation tasks, and then the edits
tracker =
gd_make_shared<AsyncDependencyTracker>(todo.size(), next_tasks, [](Span<IThreadedTask *> p_next_tasks) {
tracker = make_shared_instance<AsyncDependencyTracker>(
todo.size(), next_tasks, [](Span<IThreadedTask *> p_next_tasks) {
VoxelServer::get_singleton().push_async_tasks(p_next_tasks);
});

View File

@ -1397,7 +1397,7 @@ void test_run_blocky_random_tick() {
const Box3i world_blocks_box(-4, -4, -4, 8, 8, 8);
world_blocks_box.for_each_cell_zxy([&map, &model_buffer](Vector3i block_pos) {
std::shared_ptr<VoxelBufferInternal> buffer = gd_make_shared<VoxelBufferInternal>();
std::shared_ptr<VoxelBufferInternal> buffer = make_shared_instance<VoxelBufferInternal>();
buffer->create(model_buffer.get_size());
buffer->copy_from(model_buffer);
map.set_block_buffer(block_pos, buffer, false);

View File

@ -1,6 +1,7 @@
#include "expression_parser.h"
#include <core/math/math_funcs.h>
#include <core/os/memory.h>
#include <algorithm>
#include <sstream>
#include <vector>

View File

@ -36,28 +36,13 @@ inline bool try_get_as(const Ref<From_T> &from, Ref<To_T> &to) {
return to.is_valid();
}
// Creates a shared_ptr which will use Godot's allocation functions
// Creates a shared_ptr which will always use Godot's allocation functions
template <typename T>
inline std::shared_ptr<T> gd_make_shared() {
// std::make_shared() apparently wont allow us to specify custom new and delete
return std::shared_ptr<T>(memnew(T), memdelete<T>);
}
template <typename T, typename Arg_T>
inline std::shared_ptr<T> gd_make_shared(Arg_T arg) {
return std::shared_ptr<T>(memnew(T(arg)), memdelete<T>);
}
template <typename T, typename Arg0_T, typename Arg1_T>
inline std::shared_ptr<T> gd_make_shared(Arg0_T arg0, Arg1_T arg1) {
return std::shared_ptr<T>(memnew(T(arg0, arg1)), memdelete<T>);
}
template <typename T, typename Arg0_T, typename Arg1_T, typename Arg2_T>
inline std::shared_ptr<T> gd_make_shared(Arg0_T arg0, Arg1_T arg1, Arg2_T arg2) {
return std::shared_ptr<T>(memnew(T(arg0, arg1, arg2)), memdelete<T>);
}
// For use with smart pointers such as std::unique_ptr
template <typename T>
struct GodotObjectDeleter {
@ -66,14 +51,14 @@ struct GodotObjectDeleter {
}
};
// Specialization of `std::unique_ptr which uses `memdelete()` as deleter.
// Specialization of `std::unique_ptr which always uses Godot's `memdelete()` as deleter.
template <typename T>
using GodotUniqueObjectPtr = std::unique_ptr<T, GodotObjectDeleter<T>>;
using GodotObjectUniquePtr = std::unique_ptr<T, GodotObjectDeleter<T>>;
// Creates a `GodotUniqueObjectPtr<T>` with an object constructed with `memnew()` inside.
// Creates a `GodotObjectUniquePtr<T>` with an object constructed with `memnew()` inside.
template <typename T>
GodotUniqueObjectPtr<T> gd_make_unique() {
return GodotUniqueObjectPtr<T>(memnew(T));
GodotObjectUniquePtr<T> gd_make_unique() {
return GodotObjectUniquePtr<T>(memnew(T));
}
void set_nodes_owner(Node *root, Node *owner);

View File

@ -1,11 +1,9 @@
#ifndef VOXEL_MACROS_H
#define VOXEL_MACROS_H
#include <core/string/ustring.h>
#ifndef ZYLANN_MACROS_H
#define ZYLANN_MACROS_H
// Macros I couldn't put anywhere specific
// TODO Waiting for a fix, Variant() can't be constructed from `size_t` on JavaScript and OSX builds.
// TODO Waiting for a fix, Godot's Variant() can't be constructed from `size_t` on JavaScript and OSX builds.
// See https://github.com/godotengine/godot/issues/36690
#define ZN_SIZE_T_TO_VARIANT(s) static_cast<int64_t>(s)
@ -13,10 +11,16 @@
// Godot does not define the TTR macro for translation of messages in release builds. However, there are some non-editor
// code that can produce errors in this module, and we still want them to compile properly.
#ifdef TOOLS_ENABLED
#if defined(ZN_GODOT) && defined(TOOLS_ENABLED)
#include <core/string/ustring.h>
#define ZN_TTR(msg) TTR(msg)
#else
#define ZN_TTR(msg) msg
#endif
#endif // VOXEL_MACROS_H
#endif // ZYLANN_MACROS_H

View File

@ -3,18 +3,60 @@
#include <memory>
// Default new and delete operators.
#ifdef ZN_GODOT
#include <core/os/memory.h>
// Use Godot's allocator.
// In modules, memnew and memdelete work for anything. However in GDExtension it might not be the case...
#define ZN_NEW(t) memnew(t)
#define ZN_DELETE(t) memdelete(t)
#else
#define ZN_NEW(t) new t
#define ZN_DELETE(t) delete t
#endif
namespace zylann {
// Default implementation of unique pointers for this project. Allows to change it in one place.
// Note: array allocations are not used. Containers are preferred.
// TODO Use Godot's allocator?
// Default, engine-agnostic implementation of unique pointers for this project. Allows to change it in one place.
// Note: array allocations are not used at the moment. Containers are preferred.
template <typename T>
using UniquePtr = std::unique_ptr<T>;
struct DefaultObjectDeleter {
constexpr DefaultObjectDeleter() noexcept = default;
// This is required so we can implicitely convert from `UniquePtr<Derived>` to `UniquePtr<Base>`.
// Looked it up from inside MSVC's STL implementation.
template <class U, std::enable_if_t<std::is_convertible_v<U *, T *>, int> = 0>
DefaultObjectDeleter(const DefaultObjectDeleter<U> &) noexcept {}
inline void operator()(T *obj) {
ZN_DELETE(obj);
}
};
template <typename T>
using UniquePtr = std::unique_ptr<T, DefaultObjectDeleter<T>>;
template <class T, class... Types, std::enable_if_t<!std::is_array_v<T>, int> = 0>
UniquePtr<T> make_unique_instance(Types &&...args) {
return std::unique_ptr<T>(new T(std::forward<Types>(args)...));
return UniquePtr<T>(ZN_NEW(T(std::forward<Types>(args)...)));
}
// Default, engine-agnostic implementation of shared pointers for this project.
template <class T, class... Types, std::enable_if_t<!std::is_array_v<T>, int> = 0>
inline std::shared_ptr<T> make_shared_instance(Types &&...args) {
#ifdef ZN_GODOT
// Use Godot's allocator
return std::shared_ptr<T>(memnew(T(std::forward<Types>(args)...)), memdelete<T>);
#else
return std::shared_ptr<T>(new T(std::forward<Types>(args)...));
#endif
}
} // namespace zylann

View File

@ -1,7 +1,7 @@
#ifndef OBJECT_POOL_H
#define OBJECT_POOL_H
#include "core/os/memory.h"
#include "memory.h"
#include <vector>
namespace zylann {
@ -11,7 +11,7 @@ class ObjectPool {
public:
T *create() {
if (_objects.empty()) {
return memnew(T);
return ZN_NEW(T);
} else {
T *obj = _objects.back();
_objects.pop_back();
@ -25,8 +25,8 @@ public:
}
~ObjectPool() {
for (auto it = _objects.begin(); it != _objects.end(); ++it) {
memdelete(*it);
for (T *obj : _objects) {
ZN_DELETE(obj);
}
}

View File

@ -1,4 +1,5 @@
#include "async_dependency_tracker.h"
#include "../memory.h"
#include "threaded_task_runner.h"
namespace zylann {
@ -28,7 +29,8 @@ AsyncDependencyTracker::AsyncDependencyTracker(
AsyncDependencyTracker::~AsyncDependencyTracker() {
for (auto it = _next_tasks.begin(); it != _next_tasks.end(); ++it) {
IThreadedTask *task = *it;
memdelete(task);
// TODO Might want to allow customizing that, maybe calling a `->dispose()` function instead?
ZN_DELETE(task);
}
}