Renamed ArraySlice -> Span
This commit is contained in:
parent
2e9d817246
commit
411be94559
@ -112,7 +112,7 @@ For the most part, use `clang-format` and follow Godot conventions.
|
||||
- Avoid using macros to define logic or constants. Prefer `static const`, `constexpr` and `inline` functions.
|
||||
- Prefer adding `const` to variables that won't change after being initialized
|
||||
- Don't exploit booleanization. Example: use `if (a == nullptr)` instead of `if (a)`
|
||||
- If possible, avoid plain arrays like `int a[42]`. Debuggers don't catch overruns on them. Prefer using wrappers such as `FixedArray` and `ArraySlice` (or `std::array` and `std::span` once [this](https://github.com/godotengine/godot/issues/31608) is fixed)
|
||||
- If possible, avoid plain arrays like `int a[42]`. Debuggers don't catch overruns on them. Prefer using wrappers such as `FixedArray` and `Span` (or `std::array` and `std::span` once [this](https://github.com/godotengine/godot/issues/31608) is fixed)
|
||||
- Use `uint32_t`, `uint16_t`, `uint8_t` in case integer size matters.
|
||||
|
||||
|
||||
|
@ -768,7 +768,7 @@ void VoxelGraphEditor::update_range_analysis_previews() {
|
||||
}
|
||||
|
||||
// Highlight only nodes that will actually run
|
||||
ArraySlice<const int> execution_map = VoxelGeneratorGraph::get_last_execution_map_debug_from_current_thread();
|
||||
Span<const int> execution_map = VoxelGeneratorGraph::get_last_execution_map_debug_from_current_thread();
|
||||
for (unsigned int i = 0; i < execution_map.size(); ++i) {
|
||||
String node_view_path = node_to_gui_name(execution_map[i]);
|
||||
VoxelGraphEditorNode *node_view =
|
||||
@ -863,9 +863,9 @@ void VoxelGraphEditor::update_slice_previews() {
|
||||
}
|
||||
|
||||
_graph->generate_set(
|
||||
ArraySlice<float>(x_vec, 0, x_vec.size()),
|
||||
ArraySlice<float>(y_vec, 0, y_vec.size()),
|
||||
ArraySlice<float>(z_vec, 0, z_vec.size()));
|
||||
Span<float>(x_vec, 0, x_vec.size()),
|
||||
Span<float>(y_vec, 0, y_vec.size()),
|
||||
Span<float>(z_vec, 0, z_vec.size()));
|
||||
|
||||
const VoxelGraphRuntime::State &last_state = VoxelGeneratorGraph::get_last_state_from_current_thread();
|
||||
|
||||
|
@ -246,7 +246,7 @@ bool VoxelGeneratorGraph::is_using_xz_caching() const {
|
||||
// TODO Optimization: generating indices and weights on every voxel of a block might be avoidable
|
||||
// Instead, we could only generate them near zero-crossings, because this is where materials will be seen.
|
||||
// The problem is that it's harder to manage at the moment, to support edited blocks and LOD...
|
||||
void VoxelGeneratorGraph::gather_indices_and_weights(ArraySlice<const WeightOutput> weight_outputs,
|
||||
void VoxelGeneratorGraph::gather_indices_and_weights(Span<const WeightOutput> weight_outputs,
|
||||
const VoxelGraphRuntime::State &state, Vector3i rmin, Vector3i rmax, int ry, VoxelBuffer &out_voxel_buffer,
|
||||
FixedArray<uint8_t, 4> spare_indices) {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
@ -255,12 +255,12 @@ void VoxelGeneratorGraph::gather_indices_and_weights(ArraySlice<const WeightOutp
|
||||
// So we choose the cases below based on non-zero outputs instead of total output count
|
||||
|
||||
// TODO Could maybe put this part outside?
|
||||
FixedArray<ArraySlice<const float>, 16> buffers;
|
||||
FixedArray<Span<const float>, 16> buffers;
|
||||
const unsigned int buffers_count = weight_outputs.size();
|
||||
for (unsigned int oi = 0; oi < buffers_count; ++oi) {
|
||||
const WeightOutput &info = weight_outputs[oi];
|
||||
const VoxelGraphRuntime::Buffer &buffer = state.get_buffer(info.output_buffer_index);
|
||||
buffers[oi] = ArraySlice<const float>(buffer.data, buffer.size);
|
||||
buffers[oi] = Span<const float>(buffer.data, buffer.size);
|
||||
}
|
||||
|
||||
if (buffers_count <= 4) {
|
||||
@ -405,9 +405,9 @@ void VoxelGeneratorGraph::generate_block(VoxelBlockRequest &input) {
|
||||
cache.y_cache.resize(slice_buffer_size);
|
||||
cache.z_cache.resize(slice_buffer_size);
|
||||
|
||||
ArraySlice<float> x_cache(cache.x_cache, 0, cache.x_cache.size());
|
||||
ArraySlice<float> y_cache(cache.y_cache, 0, cache.y_cache.size());
|
||||
ArraySlice<float> z_cache(cache.z_cache, 0, cache.z_cache.size());
|
||||
Span<float> x_cache(cache.x_cache, 0, cache.x_cache.size());
|
||||
Span<float> y_cache(cache.y_cache, 0, cache.y_cache.size());
|
||||
Span<float> z_cache(cache.z_cache, 0, cache.z_cache.size());
|
||||
|
||||
const float air_sdf = _debug_clipped_blocks ? -1.f : 1.f;
|
||||
const float matter_sdf = _debug_clipped_blocks ? 1.f : -1.f;
|
||||
@ -493,7 +493,7 @@ void VoxelGeneratorGraph::generate_block(VoxelBlockRequest &input) {
|
||||
|
||||
if (runtime_ptr->weight_outputs_count > 0) {
|
||||
gather_indices_and_weights(
|
||||
to_slice_const(runtime_ptr->weight_outputs, runtime_ptr->weight_outputs_count),
|
||||
to_span_const(runtime_ptr->weight_outputs, runtime_ptr->weight_outputs_count),
|
||||
cache.state, rmin, rmax, ry, out_buffer, spare_texture_indices);
|
||||
}
|
||||
}
|
||||
@ -504,7 +504,7 @@ void VoxelGeneratorGraph::generate_block(VoxelBlockRequest &input) {
|
||||
if (_use_optimized_execution_map) {
|
||||
// Optimize out branches of the graph that won't contribute to the result
|
||||
runtime.generate_optimized_execution_map(cache.state, cache.optimized_execution_map,
|
||||
to_slice_const(runtime_ptr->weight_output_indices, runtime_ptr->weight_outputs_count),
|
||||
to_span_const(runtime_ptr->weight_output_indices, runtime_ptr->weight_outputs_count),
|
||||
false);
|
||||
}
|
||||
|
||||
@ -527,7 +527,7 @@ void VoxelGeneratorGraph::generate_block(VoxelBlockRequest &input) {
|
||||
_use_optimized_execution_map ? &cache.optimized_execution_map : nullptr);
|
||||
|
||||
gather_indices_and_weights(
|
||||
to_slice_const(runtime_ptr->weight_outputs, runtime_ptr->weight_outputs_count),
|
||||
to_span_const(runtime_ptr->weight_outputs, runtime_ptr->weight_outputs_count),
|
||||
cache.state, rmin, rmax, ry, out_buffer, spare_texture_indices);
|
||||
}
|
||||
}
|
||||
@ -673,7 +673,7 @@ bool VoxelGeneratorGraph::is_good() const {
|
||||
return _runtime != nullptr;
|
||||
}
|
||||
|
||||
void VoxelGeneratorGraph::generate_set(ArraySlice<float> in_x, ArraySlice<float> in_y, ArraySlice<float> in_z) {
|
||||
void VoxelGeneratorGraph::generate_set(Span<float> in_x, Span<float> in_y, Span<float> in_z) {
|
||||
RWLockRead rlock(_runtime_lock);
|
||||
ERR_FAIL_COND(_runtime == nullptr);
|
||||
Cache &cache = _cache;
|
||||
@ -686,8 +686,8 @@ const VoxelGraphRuntime::State &VoxelGeneratorGraph::get_last_state_from_current
|
||||
return _cache.state;
|
||||
}
|
||||
|
||||
ArraySlice<const int> VoxelGeneratorGraph::get_last_execution_map_debug_from_current_thread() {
|
||||
return to_slice_const(_cache.optimized_execution_map.debug_nodes);
|
||||
Span<const int> VoxelGeneratorGraph::get_last_execution_map_debug_from_current_thread() {
|
||||
return to_span_const(_cache.optimized_execution_map.debug_nodes);
|
||||
}
|
||||
|
||||
bool VoxelGeneratorGraph::try_get_output_port_address(ProgramGraph::PortLocation port, uint32_t &out_address) const {
|
||||
@ -803,7 +803,7 @@ void VoxelGeneratorGraph::bake_sphere_bumpmap(Ref<Image> im, float ref_radius, f
|
||||
}
|
||||
}
|
||||
|
||||
runtime.generate_set(state, to_slice(x_coords), to_slice(y_coords), to_slice(z_coords), false, nullptr);
|
||||
runtime.generate_set(state, to_span(x_coords), to_span(y_coords), to_span(z_coords), false, nullptr);
|
||||
const VoxelGraphRuntime::Buffer &buffer = state.get_buffer(sdf_buffer_index);
|
||||
|
||||
// Calculate final pixels
|
||||
@ -913,7 +913,7 @@ void VoxelGeneratorGraph::bake_sphere_normalmap(Ref<Image> im, float ref_radius,
|
||||
}
|
||||
}
|
||||
// TODO Perform range analysis on the range of coordinates, it might still yield performance benefits
|
||||
runtime.generate_set(state, to_slice(x_coords), to_slice(y_coords), to_slice(z_coords), false, nullptr);
|
||||
runtime.generate_set(state, to_span(x_coords), to_span(y_coords), to_span(z_coords), false, nullptr);
|
||||
CRASH_COND(sdf_values_p.size() != sdf_buffer.size);
|
||||
memcpy(sdf_values_p.data(), sdf_buffer.data, sdf_values_p.size() * sizeof(float));
|
||||
|
||||
@ -929,7 +929,7 @@ void VoxelGeneratorGraph::bake_sphere_normalmap(Ref<Image> im, float ref_radius,
|
||||
++i;
|
||||
}
|
||||
}
|
||||
runtime.generate_set(state, to_slice(x_coords), to_slice(y_coords), to_slice(z_coords), false, nullptr);
|
||||
runtime.generate_set(state, to_span(x_coords), to_span(y_coords), to_span(z_coords), false, nullptr);
|
||||
CRASH_COND(sdf_values_px.size() != sdf_buffer.size);
|
||||
memcpy(sdf_values_px.data(), sdf_buffer.data, sdf_values_px.size() * sizeof(float));
|
||||
|
||||
@ -945,7 +945,7 @@ void VoxelGeneratorGraph::bake_sphere_normalmap(Ref<Image> im, float ref_radius,
|
||||
++i;
|
||||
}
|
||||
}
|
||||
runtime.generate_set(state, to_slice(x_coords), to_slice(y_coords), to_slice(z_coords), false, nullptr);
|
||||
runtime.generate_set(state, to_span(x_coords), to_span(y_coords), to_span(z_coords), false, nullptr);
|
||||
CRASH_COND(sdf_values_py.size() != sdf_buffer.size);
|
||||
memcpy(sdf_values_py.data(), sdf_buffer.data, sdf_values_py.size() * sizeof(float));
|
||||
|
||||
@ -1224,9 +1224,9 @@ float VoxelGeneratorGraph::debug_measure_microseconds_per_voxel(bool singular) {
|
||||
src_x.resize(cube_volume);
|
||||
src_y.resize(cube_volume);
|
||||
src_z.resize(cube_volume);
|
||||
ArraySlice<float> sx(src_x, 0, src_x.size());
|
||||
ArraySlice<float> sy(src_y, 0, src_y.size());
|
||||
ArraySlice<float> sz(src_z, 0, src_z.size());
|
||||
Span<float> sx(src_x, 0, src_x.size());
|
||||
Span<float> sy(src_y, 0, src_y.size());
|
||||
Span<float> sz(src_z, 0, src_z.size());
|
||||
|
||||
runtime.prepare_state(cache.state, sx.size());
|
||||
|
||||
|
@ -140,11 +140,11 @@ public:
|
||||
VoxelGraphRuntime::CompilationResult compile();
|
||||
bool is_good() const;
|
||||
|
||||
void generate_set(ArraySlice<float> in_x, ArraySlice<float> in_y, ArraySlice<float> in_z);
|
||||
void generate_set(Span<float> in_x, Span<float> in_y, Span<float> in_z);
|
||||
|
||||
// Returns state from the last generator used in the current thread
|
||||
static const VoxelGraphRuntime::State &get_last_state_from_current_thread();
|
||||
static ArraySlice<const int> get_last_execution_map_debug_from_current_thread();
|
||||
static Span<const int> get_last_execution_map_debug_from_current_thread();
|
||||
|
||||
bool try_get_output_port_address(ProgramGraph::PortLocation port, uint32_t &out_address) const;
|
||||
|
||||
@ -179,7 +179,7 @@ private:
|
||||
unsigned int output_buffer_index;
|
||||
};
|
||||
|
||||
static void gather_indices_and_weights(ArraySlice<const WeightOutput> weight_outputs,
|
||||
static void gather_indices_and_weights(Span<const WeightOutput> weight_outputs,
|
||||
const VoxelGraphRuntime::State &state, Vector3i rmin, Vector3i rmax, int ry, VoxelBuffer &out_voxel_buffer,
|
||||
FixedArray<uint8_t, 4> spare_indices);
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
//#endif
|
||||
|
||||
template <typename T>
|
||||
inline const T &read(const ArraySlice<const uint8_t> &mem, uint32_t &p) {
|
||||
inline const T &read(const Span<const uint8_t> &mem, uint32_t &p) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(p + sizeof(T) > mem.size());
|
||||
#endif
|
||||
@ -424,8 +424,8 @@ VoxelGraphRuntime::CompilationResult VoxelGraphRuntime::_compile(const ProgramGr
|
||||
return result;
|
||||
}
|
||||
|
||||
static ArraySlice<const uint16_t> get_outputs_from_op_address(
|
||||
ArraySlice<const uint8_t> operations, uint16_t op_address) {
|
||||
static Span<const uint16_t> get_outputs_from_op_address(
|
||||
Span<const uint8_t> operations, uint16_t op_address) {
|
||||
const uint8_t opid = operations[op_address];
|
||||
const VoxelGraphNodeDB::NodeType &node_type = VoxelGraphNodeDB::get_singleton()->get_type(opid);
|
||||
|
||||
@ -437,7 +437,7 @@ static ArraySlice<const uint16_t> get_outputs_from_op_address(
|
||||
}
|
||||
|
||||
bool VoxelGraphRuntime::is_operation_constant(const State &state, uint16_t op_address) const {
|
||||
ArraySlice<const uint16_t> outputs = get_outputs_from_op_address(to_slice_const(_program.operations), op_address);
|
||||
Span<const uint16_t> outputs = get_outputs_from_op_address(to_span_const(_program.operations), op_address);
|
||||
|
||||
for (unsigned int i = 0; i < outputs.size(); ++i) {
|
||||
const uint16_t output_address = outputs[i];
|
||||
@ -459,7 +459,7 @@ void VoxelGraphRuntime::generate_optimized_execution_map(const State &state, Exe
|
||||
for (unsigned int i = 0; i < _program.outputs_count; ++i) {
|
||||
all_outputs[i] = i;
|
||||
}
|
||||
generate_optimized_execution_map(state, execution_map, to_slice_const(all_outputs, _program.outputs_count), debug);
|
||||
generate_optimized_execution_map(state, execution_map, to_span_const(all_outputs, _program.outputs_count), debug);
|
||||
}
|
||||
|
||||
// Generates a list of adresses for the operations to execute,
|
||||
@ -468,7 +468,7 @@ void VoxelGraphRuntime::generate_optimized_execution_map(const State &state, Exe
|
||||
// This has the effect of optimizing locally at runtime without relying on explicit conditionals.
|
||||
// It can be useful for biomes, where some branches become constant when not used in the final blending.
|
||||
void VoxelGraphRuntime::generate_optimized_execution_map(const State &state, ExecutionMap &execution_map,
|
||||
ArraySlice<const unsigned int> required_outputs, bool debug) const {
|
||||
Span<const unsigned int> required_outputs, bool debug) const {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
// Range analysis results must have been computed
|
||||
@ -548,7 +548,7 @@ void VoxelGraphRuntime::generate_optimized_execution_map(const State &state, Exe
|
||||
}
|
||||
}
|
||||
|
||||
ArraySlice<const uint8_t> operations(program.operations.data(), 0, program.operations.size());
|
||||
Span<const uint8_t> operations(program.operations.data(), 0, program.operations.size());
|
||||
bool xzy_start_not_assigned = true;
|
||||
|
||||
// Now we have to fill buffers with the local constants we may have found.
|
||||
@ -566,7 +566,7 @@ void VoxelGraphRuntime::generate_optimized_execution_map(const State &state, Exe
|
||||
continue;
|
||||
|
||||
case SKIPPABLE: {
|
||||
const ArraySlice<const uint16_t> outputs = get_outputs_from_op_address(operations, node.op_address);
|
||||
const Span<const uint16_t> outputs = get_outputs_from_op_address(operations, node.op_address);
|
||||
|
||||
for (unsigned int output_index = 0; output_index < outputs.size(); ++output_index) {
|
||||
const uint16_t output_address = outputs[output_index];
|
||||
@ -612,9 +612,9 @@ void VoxelGraphRuntime::generate_optimized_execution_map(const State &state, Exe
|
||||
|
||||
void VoxelGraphRuntime::generate_single(State &state, Vector3 position, const ExecutionMap *execution_map) const {
|
||||
generate_set(state,
|
||||
ArraySlice<float>(&position.x, 1),
|
||||
ArraySlice<float>(&position.y, 1),
|
||||
ArraySlice<float>(&position.z, 1), false, execution_map);
|
||||
Span<float>(&position.x, 1),
|
||||
Span<float>(&position.y, 1),
|
||||
Span<float>(&position.z, 1), false, execution_map);
|
||||
}
|
||||
|
||||
void VoxelGraphRuntime::prepare_state(State &state, unsigned int buffer_size) const {
|
||||
@ -624,7 +624,7 @@ void VoxelGraphRuntime::prepare_state(State &state, unsigned int buffer_size) co
|
||||
}
|
||||
|
||||
// Note: this must be after we resize the vector
|
||||
ArraySlice<Buffer> buffers(state.buffers, 0, state.buffers.size());
|
||||
Span<Buffer> buffers(state.buffers, 0, state.buffers.size());
|
||||
state.buffer_size = buffer_size;
|
||||
|
||||
for (auto it = _program.buffer_specs.cbegin(); it != _program.buffer_specs.cend(); ++it) {
|
||||
@ -731,18 +731,18 @@ void VoxelGraphRuntime::prepare_state(State &state, unsigned int buffer_size) co
|
||||
}
|
||||
|
||||
void VoxelGraphRuntime::generate_set(State &state,
|
||||
ArraySlice<float> in_x, ArraySlice<float> in_y, ArraySlice<float> in_z, bool skip_xz,
|
||||
Span<float> in_x, Span<float> in_y, Span<float> in_z, bool skip_xz,
|
||||
const ExecutionMap *execution_map) const {
|
||||
// I don't like putting private helper functions in headers.
|
||||
struct L {
|
||||
static inline void bind_buffer(ArraySlice<Buffer> buffers, int a, ArraySlice<float> d) {
|
||||
static inline void bind_buffer(Span<Buffer> buffers, int a, Span<float> d) {
|
||||
Buffer &buffer = buffers[a];
|
||||
CRASH_COND(!buffer.is_binding);
|
||||
buffer.data = d.data();
|
||||
buffer.size = d.size();
|
||||
}
|
||||
|
||||
static inline void unbind_buffer(ArraySlice<Buffer> buffers, int a) {
|
||||
static inline void unbind_buffer(Span<Buffer> buffers, int a) {
|
||||
Buffer &buffer = buffers[a];
|
||||
CRASH_COND(!buffer.is_binding);
|
||||
buffer.data = nullptr;
|
||||
@ -776,7 +776,7 @@ void VoxelGraphRuntime::generate_set(State &state,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ArraySlice<Buffer> buffers(state.buffers, 0, state.buffers.size());
|
||||
Span<Buffer> buffers(state.buffers, 0, state.buffers.size());
|
||||
|
||||
// Bind inputs
|
||||
if (_program.x_input_address != -1) {
|
||||
@ -789,11 +789,11 @@ void VoxelGraphRuntime::generate_set(State &state,
|
||||
L::bind_buffer(buffers, _program.z_input_address, in_z);
|
||||
}
|
||||
|
||||
const ArraySlice<const uint8_t> operations(_program.operations.data(), 0, _program.operations.size());
|
||||
const Span<const uint8_t> operations(_program.operations.data(), 0, _program.operations.size());
|
||||
|
||||
ArraySlice<const uint16_t> op_adresses = execution_map != nullptr ?
|
||||
to_slice_const(execution_map->operation_adresses) :
|
||||
to_slice_const(_program.default_execution_map.operation_adresses);
|
||||
Span<const uint16_t> op_adresses = execution_map != nullptr ?
|
||||
to_span_const(execution_map->operation_adresses) :
|
||||
to_span_const(_program.default_execution_map.operation_adresses);
|
||||
if (skip_xz && op_adresses.size() > 0) {
|
||||
const unsigned int offset = execution_map != nullptr ?
|
||||
execution_map->xzy_start_index :
|
||||
@ -810,15 +810,15 @@ void VoxelGraphRuntime::generate_set(State &state,
|
||||
const uint32_t inputs_size = node_type.inputs.size() * sizeof(uint16_t);
|
||||
const uint32_t outputs_size = node_type.outputs.size() * sizeof(uint16_t);
|
||||
|
||||
const ArraySlice<const uint16_t> inputs =
|
||||
const Span<const uint16_t> inputs =
|
||||
operations.sub(pc, inputs_size).reinterpret_cast_to<const uint16_t>();
|
||||
pc += inputs_size;
|
||||
const ArraySlice<const uint16_t> outputs =
|
||||
const Span<const uint16_t> outputs =
|
||||
operations.sub(pc, outputs_size).reinterpret_cast_to<const uint16_t>();
|
||||
pc += outputs_size;
|
||||
|
||||
const uint16_t params_size = read<uint16_t>(operations, pc);
|
||||
ArraySlice<const uint8_t> params;
|
||||
Span<const uint8_t> params;
|
||||
if (params_size > 0) {
|
||||
params = operations.sub(pc, params_size);
|
||||
//pc += params_size;
|
||||
@ -849,8 +849,8 @@ void VoxelGraphRuntime::analyze_range(State &state, Vector3i min_pos, Vector3i m
|
||||
ERR_FAIL_COND(state.ranges.size() != _program.buffer_count);
|
||||
#endif
|
||||
|
||||
ArraySlice<Interval> ranges(state.ranges, 0, state.ranges.size());
|
||||
ArraySlice<Buffer> buffers(state.buffers, 0, state.buffers.size());
|
||||
Span<Interval> ranges(state.ranges, 0, state.ranges.size());
|
||||
Span<Buffer> buffers(state.buffers, 0, state.buffers.size());
|
||||
|
||||
// Reset users count, as they might be decreased during the analysis
|
||||
for (auto it = _program.buffer_specs.cbegin(); it != _program.buffer_specs.cend(); ++it) {
|
||||
@ -863,7 +863,7 @@ void VoxelGraphRuntime::analyze_range(State &state, Vector3i min_pos, Vector3i m
|
||||
ranges[_program.y_input_address] = Interval(min_pos.y, max_pos.y);
|
||||
ranges[_program.z_input_address] = Interval(min_pos.z, max_pos.z);
|
||||
|
||||
const ArraySlice<const uint8_t> operations(_program.operations.data(), 0, _program.operations.size());
|
||||
const Span<const uint8_t> operations(_program.operations.data(), 0, _program.operations.size());
|
||||
|
||||
// Here operations must all be analyzed, because we do this as a broad-phase.
|
||||
// Only narrow-phase may skip some operations eventually.
|
||||
@ -875,15 +875,15 @@ void VoxelGraphRuntime::analyze_range(State &state, Vector3i min_pos, Vector3i m
|
||||
const uint32_t inputs_size = node_type.inputs.size() * sizeof(uint16_t);
|
||||
const uint32_t outputs_size = node_type.outputs.size() * sizeof(uint16_t);
|
||||
|
||||
const ArraySlice<const uint16_t> inputs =
|
||||
const Span<const uint16_t> inputs =
|
||||
operations.sub(pc, inputs_size).reinterpret_cast_to<const uint16_t>();
|
||||
pc += inputs_size;
|
||||
const ArraySlice<const uint16_t> outputs =
|
||||
const Span<const uint16_t> outputs =
|
||||
operations.sub(pc, outputs_size).reinterpret_cast_to<const uint16_t>();
|
||||
pc += outputs_size;
|
||||
|
||||
const uint16_t params_size = read<uint16_t>(operations, pc);
|
||||
ArraySlice<const uint8_t> params;
|
||||
Span<const uint8_t> params;
|
||||
if (params_size > 0) {
|
||||
params = operations.sub(pc, params_size);
|
||||
pc += params_size;
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifndef VOXEL_GRAPH_RUNTIME_H
|
||||
#define VOXEL_GRAPH_RUNTIME_H
|
||||
|
||||
#include "../../util/array_slice.h"
|
||||
#include "../../util/math/interval.h"
|
||||
#include "../../util/math/vector3i.h"
|
||||
#include "../../util/span.h"
|
||||
#include "program_graph.h"
|
||||
|
||||
#include <core/reference.h>
|
||||
@ -120,7 +120,7 @@ public:
|
||||
// Convenience for set generation with only one value
|
||||
void generate_single(State &state, Vector3 position, const ExecutionMap *execution_map) const;
|
||||
|
||||
void generate_set(State &state, ArraySlice<float> in_x, ArraySlice<float> in_y, ArraySlice<float> in_z,
|
||||
void generate_set(State &state, Span<float> in_x, Span<float> in_y, Span<float> in_z,
|
||||
bool skip_xz, const ExecutionMap *execution_map) const;
|
||||
|
||||
inline unsigned int get_output_count() const {
|
||||
@ -140,7 +140,7 @@ public:
|
||||
// This allows to use the execution map optimization, until you choose another area.
|
||||
// (i.e when using this, querying values outside of the analyzed area may be invalid)
|
||||
void generate_optimized_execution_map(const State &state, ExecutionMap &execution_map,
|
||||
ArraySlice<const unsigned int> required_outputs, bool debug) const;
|
||||
Span<const unsigned int> required_outputs, bool debug) const;
|
||||
|
||||
// Convenience function to require all outputs
|
||||
void generate_optimized_execution_map(const State &state, ExecutionMap &execution_map, bool debug) const;
|
||||
@ -219,9 +219,9 @@ public:
|
||||
class _ProcessContext {
|
||||
public:
|
||||
inline _ProcessContext(
|
||||
const ArraySlice<const uint16_t> inputs,
|
||||
const ArraySlice<const uint16_t> outputs,
|
||||
const ArraySlice<const uint8_t> params) :
|
||||
const Span<const uint16_t> inputs,
|
||||
const Span<const uint16_t> outputs,
|
||||
const Span<const uint8_t> params) :
|
||||
_inputs(inputs),
|
||||
_outputs(outputs),
|
||||
_params(params) {}
|
||||
@ -241,19 +241,19 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const ArraySlice<const uint16_t> _inputs;
|
||||
const ArraySlice<const uint16_t> _outputs;
|
||||
const ArraySlice<const uint8_t> _params;
|
||||
const Span<const uint16_t> _inputs;
|
||||
const Span<const uint16_t> _outputs;
|
||||
const Span<const uint8_t> _params;
|
||||
};
|
||||
|
||||
// Functions usable by node implementations during execution
|
||||
class ProcessBufferContext : public _ProcessContext {
|
||||
public:
|
||||
inline ProcessBufferContext(
|
||||
const ArraySlice<const uint16_t> inputs,
|
||||
const ArraySlice<const uint16_t> outputs,
|
||||
const ArraySlice<const uint8_t> params,
|
||||
ArraySlice<Buffer> buffers,
|
||||
const Span<const uint16_t> inputs,
|
||||
const Span<const uint16_t> outputs,
|
||||
const Span<const uint8_t> params,
|
||||
Span<Buffer> buffers,
|
||||
bool using_execution_map) :
|
||||
_ProcessContext(inputs, outputs, params),
|
||||
_buffers(buffers),
|
||||
@ -287,7 +287,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
ArraySlice<Buffer> _buffers;
|
||||
Span<Buffer> _buffers;
|
||||
bool _using_execution_map;
|
||||
};
|
||||
|
||||
@ -295,11 +295,11 @@ public:
|
||||
class RangeAnalysisContext : public _ProcessContext {
|
||||
public:
|
||||
inline RangeAnalysisContext(
|
||||
const ArraySlice<const uint16_t> inputs,
|
||||
const ArraySlice<const uint16_t> outputs,
|
||||
const ArraySlice<const uint8_t> params,
|
||||
ArraySlice<Interval> ranges,
|
||||
ArraySlice<Buffer> buffers) :
|
||||
const Span<const uint16_t> inputs,
|
||||
const Span<const uint16_t> outputs,
|
||||
const Span<const uint8_t> params,
|
||||
Span<Interval> ranges,
|
||||
Span<Buffer> buffers) :
|
||||
_ProcessContext(inputs, outputs, params),
|
||||
_ranges(ranges),
|
||||
_buffers(buffers) {}
|
||||
@ -321,8 +321,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
ArraySlice<Interval> _ranges;
|
||||
ArraySlice<Buffer> _buffers;
|
||||
Span<Interval> _ranges;
|
||||
Span<Buffer> _buffers;
|
||||
};
|
||||
|
||||
typedef void (*CompileFunc)(CompileContext &);
|
||||
@ -391,7 +391,7 @@ private:
|
||||
|
||||
// Heap-allocated parameters data, when too large to fit in `operations`.
|
||||
// We keep a reference to them so they won't be freed until the program is cleared.
|
||||
std::vector<Ref<Reference> > ref_resources;
|
||||
std::vector<Ref<Reference>> ref_resources;
|
||||
|
||||
// Describes the list of buffers to prepare in `State` before the program can be run
|
||||
std::vector<BufferSpec> buffer_specs;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "voxel_generator_heightmap.h"
|
||||
#include "../../util/array_slice.h"
|
||||
#include "../../util/fixed_array.h"
|
||||
#include "../../util/span.h"
|
||||
|
||||
VoxelGeneratorHeightmap::VoxelGeneratorHeightmap() {
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "voxel_generator_image.h"
|
||||
#include "../../util/array_slice.h"
|
||||
#include "../../util/fixed_array.h"
|
||||
#include "../../util/span.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "voxel_mesher_blocky.h"
|
||||
#include "../../constants/cube_tables.h"
|
||||
#include "../../storage/voxel_buffer.h"
|
||||
#include "../../util/array_slice.h"
|
||||
#include "../../util/funcs.h"
|
||||
#include "../../util/span.h"
|
||||
#include <core/os/os.h>
|
||||
|
||||
// Utility functions
|
||||
@ -52,11 +52,10 @@ inline bool contributes_to_ao(const VoxelLibrary::BakedData &lib, uint32_t voxel
|
||||
template <typename Type_T>
|
||||
static void generate_blocky_mesh(
|
||||
FixedArray<VoxelMesherBlocky::Arrays, VoxelMesherBlocky::MAX_MATERIALS> &out_arrays_per_material,
|
||||
const ArraySlice<Type_T> type_buffer,
|
||||
const Span<Type_T> type_buffer,
|
||||
const Vector3i block_size,
|
||||
const VoxelLibrary::BakedData &library,
|
||||
bool bake_occlusion, float baked_occlusion_darkness) {
|
||||
|
||||
ERR_FAIL_COND(block_size.x < static_cast<int>(2 * VoxelMesherBlocky::PADDING) ||
|
||||
block_size.y < static_cast<int>(2 * VoxelMesherBlocky::PADDING) ||
|
||||
block_size.z < static_cast<int>(2 * VoxelMesherBlocky::PADDING));
|
||||
@ -448,7 +447,7 @@ void VoxelMesherBlocky::build(VoxelMesher::Output &output, const VoxelMesher::In
|
||||
return;
|
||||
}
|
||||
|
||||
ArraySlice<uint8_t> raw_channel;
|
||||
Span<uint8_t> raw_channel;
|
||||
if (!voxels.get_channel_raw(channel, raw_channel)) {
|
||||
/* _
|
||||
// | \
|
||||
@ -495,7 +494,6 @@ void VoxelMesherBlocky::build(VoxelMesher::Output &output, const VoxelMesher::In
|
||||
for (unsigned int i = 0; i < MAX_MATERIALS; ++i) {
|
||||
const Arrays &arrays = cache.arrays_per_material[i];
|
||||
if (arrays.positions.size() != 0) {
|
||||
|
||||
Array mesh_arrays;
|
||||
mesh_arrays.resize(Mesh::ARRAY_MAX);
|
||||
|
||||
|
@ -60,10 +60,9 @@ inline uint8_t get_alpha_index(Color8 c) {
|
||||
template <typename Voxel_T, typename Color_F>
|
||||
void build_voxel_mesh_as_simple_cubes(
|
||||
FixedArray<VoxelMesherCubes::Arrays, VoxelMesherCubes::MATERIAL_COUNT> &out_arrays_per_material,
|
||||
const ArraySlice<Voxel_T> voxel_buffer,
|
||||
const Span<Voxel_T> voxel_buffer,
|
||||
const Vector3i block_size,
|
||||
Color_F color_func) {
|
||||
|
||||
ERR_FAIL_COND(block_size.x < static_cast<int>(2 * VoxelMesherCubes::PADDING) ||
|
||||
block_size.y < static_cast<int>(2 * VoxelMesherCubes::PADDING) ||
|
||||
block_size.z < static_cast<int>(2 * VoxelMesherCubes::PADDING));
|
||||
@ -193,11 +192,10 @@ void build_voxel_mesh_as_simple_cubes(
|
||||
template <typename Voxel_T, typename Color_F>
|
||||
void build_voxel_mesh_as_greedy_cubes(
|
||||
FixedArray<VoxelMesherCubes::Arrays, VoxelMesherCubes::MATERIAL_COUNT> &out_arrays_per_material,
|
||||
const ArraySlice<Voxel_T> voxel_buffer,
|
||||
const Span<Voxel_T> voxel_buffer,
|
||||
const Vector3i block_size,
|
||||
std::vector<uint8_t> mask_memory_pool,
|
||||
Color_F color_func) {
|
||||
|
||||
ERR_FAIL_COND(block_size.x < static_cast<int>(2 * VoxelMesherCubes::PADDING) ||
|
||||
block_size.y < static_cast<int>(2 * VoxelMesherCubes::PADDING) ||
|
||||
block_size.z < static_cast<int>(2 * VoxelMesherCubes::PADDING));
|
||||
@ -238,7 +236,7 @@ void build_voxel_mesh_as_greedy_cubes(
|
||||
const unsigned int mask_area = mask_size_x * mask_size_y;
|
||||
// Using the vector as memory pool
|
||||
mask_memory_pool.resize(mask_area * sizeof(MaskValue));
|
||||
ArraySlice<MaskValue> mask(reinterpret_cast<MaskValue *>(mask_memory_pool.data()), 0, mask_area);
|
||||
Span<MaskValue> mask(reinterpret_cast<MaskValue *>(mask_memory_pool.data()), 0, mask_area);
|
||||
|
||||
// For each deck
|
||||
for (unsigned int d = min_pos[za] - VoxelMesherCubes::PADDING; d < (unsigned int)max_pos[za]; ++d) {
|
||||
@ -280,7 +278,7 @@ void build_voxel_mesh_as_greedy_cubes(
|
||||
|
||||
struct L {
|
||||
static inline bool is_range_equal(
|
||||
const ArraySlice<MaskValue> &mask, unsigned int xmin, unsigned int xmax, MaskValue v) {
|
||||
const Span<MaskValue> &mask, unsigned int xmin, unsigned int xmax, MaskValue v) {
|
||||
for (unsigned int x = xmin; x < xmax; ++x) {
|
||||
if (mask[x] != v) {
|
||||
return false;
|
||||
@ -426,7 +424,7 @@ void VoxelMesherCubes::build(VoxelMesher::Output &output, const VoxelMesher::Inp
|
||||
return;
|
||||
}
|
||||
|
||||
ArraySlice<uint8_t> raw_channel;
|
||||
Span<uint8_t> raw_channel;
|
||||
if (!voxels.get_channel_raw(channel, raw_channel)) {
|
||||
// Case supposedly handled before...
|
||||
ERR_PRINT("Something wrong happened");
|
||||
|
@ -125,7 +125,7 @@ inline float sdf_as_float(double v) {
|
||||
|
||||
template <typename Sdf_T>
|
||||
inline Vector3 get_corner_gradient(
|
||||
unsigned int data_index, ArraySlice<const Sdf_T> sdf_data, const Vector3i block_size) {
|
||||
unsigned int data_index, Span<const Sdf_T> sdf_data, const Vector3i block_size) {
|
||||
const unsigned int n010 = 1; // Y+1
|
||||
const unsigned int n100 = block_size.y; // X+1
|
||||
const unsigned int n001 = block_size.y * block_size.x; // Z+1
|
||||
@ -168,7 +168,7 @@ struct CellTextureDatas {
|
||||
|
||||
template <unsigned int NVoxels, typename WeightSampler_T>
|
||||
CellTextureDatas<NVoxels> select_textures(const FixedArray<unsigned int, NVoxels> &voxel_indices,
|
||||
ArraySlice<const uint16_t> indices_data, const WeightSampler_T &weights_sampler) {
|
||||
Span<const uint16_t> indices_data, const WeightSampler_T &weights_sampler) {
|
||||
// TODO Optimization: this function takes almost half of the time when polygonizing non-empty cells.
|
||||
// I wonder how it can be optimized further?
|
||||
|
||||
@ -242,7 +242,7 @@ CellTextureDatas<NVoxels> select_textures(const FixedArray<unsigned int, NVoxels
|
||||
}
|
||||
|
||||
struct TextureIndicesData {
|
||||
ArraySlice<const uint16_t> buffer;
|
||||
Span<const uint16_t> buffer;
|
||||
FixedArray<uint8_t, 4> default_indices;
|
||||
uint32_t packed_default_indices;
|
||||
};
|
||||
@ -288,7 +288,7 @@ inline float get_isolevel<float>() {
|
||||
// This function is template so we avoid branches and checks when sampling voxels
|
||||
template <typename Sdf_T, typename WeightSampler_T>
|
||||
void build_regular_mesh(
|
||||
ArraySlice<const Sdf_T> sdf_data,
|
||||
Span<const Sdf_T> sdf_data,
|
||||
TextureIndicesData texture_indices_data,
|
||||
const WeightSampler_T &weights_sampler,
|
||||
const Vector3i block_size_with_padding,
|
||||
@ -724,7 +724,7 @@ inline void get_face_axes(int &ax, int &ay, int dir) {
|
||||
|
||||
template <typename Sdf_T, typename WeightSampler_T>
|
||||
void build_transition_mesh(
|
||||
ArraySlice<const Sdf_T> sdf_data,
|
||||
Span<const Sdf_T> sdf_data,
|
||||
TextureIndicesData texture_indices_data,
|
||||
const WeightSampler_T &weights_sampler,
|
||||
const Vector3i block_size_with_padding,
|
||||
@ -1119,10 +1119,11 @@ void build_transition_mesh(
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ArraySlice<const T> get_or_decompress_channel(
|
||||
Span<const T> get_or_decompress_channel(
|
||||
const VoxelBuffer &voxels, std::vector<T> &backing_buffer, unsigned int channel) {
|
||||
//
|
||||
ERR_FAIL_COND_V(voxels.get_channel_depth(channel) != VoxelBuffer::get_depth_from_size(sizeof(T)),
|
||||
ArraySlice<const T>());
|
||||
Span<const T>());
|
||||
|
||||
if (voxels.get_channel_compression(channel) == VoxelBuffer::COMPRESSION_UNIFORM) {
|
||||
backing_buffer.resize(voxels.get_size().volume());
|
||||
@ -1131,10 +1132,10 @@ ArraySlice<const T> get_or_decompress_channel(
|
||||
for (unsigned int i = 0; i < backing_buffer.size(); ++i) {
|
||||
backing_buffer[i] = v;
|
||||
}
|
||||
return to_slice_const(backing_buffer);
|
||||
return to_span_const(backing_buffer);
|
||||
|
||||
} else {
|
||||
ArraySlice<uint8_t> data_bytes;
|
||||
Span<uint8_t> data_bytes;
|
||||
CRASH_COND(voxels.get_channel_raw(channel, data_bytes) == false);
|
||||
return data_bytes.reinterpret_cast_to<const T>();
|
||||
}
|
||||
@ -1156,7 +1157,7 @@ TextureIndicesData get_texture_indices_data(const VoxelBuffer &voxels, unsigned
|
||||
out_default_texture_indices_data.use = true;
|
||||
|
||||
} else {
|
||||
ArraySlice<uint8_t> data_bytes;
|
||||
Span<uint8_t> data_bytes;
|
||||
CRASH_COND(voxels.get_channel_raw(channel, data_bytes) == false);
|
||||
data.buffer = data_bytes.reinterpret_cast_to<const uint16_t>();
|
||||
|
||||
@ -1172,9 +1173,9 @@ TextureIndicesData get_texture_indices_data(const VoxelBuffer &voxels, unsigned
|
||||
#ifdef USE_TRICHANNEL
|
||||
// TODO Is this a faster/equivalent option with better precision?
|
||||
struct WeightSampler3U8 {
|
||||
ArraySlice<const uint8_t> u8_data0;
|
||||
ArraySlice<const uint8_t> u8_data1;
|
||||
ArraySlice<const uint8_t> u8_data2;
|
||||
Span<const uint8_t> u8_data0;
|
||||
Span<const uint8_t> u8_data1;
|
||||
Span<const uint8_t> u8_data2;
|
||||
inline FixedArray<uint8_t, 4> get_weights(int i) const {
|
||||
FixedArray<uint8_t, 4> w;
|
||||
w[0] = u8_data0[i];
|
||||
@ -1191,7 +1192,7 @@ thread_local std::vector<uint8_t> s_weights_backing_buffer_u8_2;
|
||||
|
||||
#else
|
||||
struct WeightSamplerPackedU16 {
|
||||
ArraySlice<const uint16_t> u16_data;
|
||||
Span<const uint16_t> u16_data;
|
||||
inline FixedArray<uint8_t, 4> get_weights(int i) const {
|
||||
return decode_weights_from_packed_u16(u16_data[i]);
|
||||
}
|
||||
@ -1205,7 +1206,7 @@ DefaultTextureIndicesData build_regular_mesh(const VoxelBuffer &voxels, unsigned
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
// From this point, we expect the buffer to contain allocated data in the relevant channels.
|
||||
|
||||
ArraySlice<uint8_t> sdf_data_raw;
|
||||
Span<uint8_t> sdf_data_raw;
|
||||
CRASH_COND(voxels.get_channel_raw(sdf_channel, sdf_data_raw) == false);
|
||||
|
||||
const unsigned int voxels_count = voxels.get_size().volume();
|
||||
@ -1245,19 +1246,19 @@ DefaultTextureIndicesData build_regular_mesh(const VoxelBuffer &voxels, unsigned
|
||||
// which would otherwise harm performance in tight iterations
|
||||
switch (voxels.get_channel_depth(sdf_channel)) {
|
||||
case VoxelBuffer::DEPTH_8_BIT: {
|
||||
ArraySlice<const uint8_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint8_t>();
|
||||
Span<const uint8_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint8_t>();
|
||||
build_regular_mesh<uint8_t>(
|
||||
sdf_data, indices_data, weights_data, voxels.get_size(), lod_index, texturing_mode, cache, output);
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::DEPTH_16_BIT: {
|
||||
ArraySlice<const uint16_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint16_t>();
|
||||
Span<const uint16_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint16_t>();
|
||||
build_regular_mesh<uint16_t>(
|
||||
sdf_data, indices_data, weights_data, voxels.get_size(), lod_index, texturing_mode, cache, output);
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::DEPTH_32_BIT: {
|
||||
ArraySlice<const float> sdf_data = sdf_data_raw.reinterpret_cast_to<const float>();
|
||||
Span<const float> sdf_data = sdf_data_raw.reinterpret_cast_to<const float>();
|
||||
build_regular_mesh<float>(
|
||||
sdf_data, indices_data, weights_data, voxels.get_size(), lod_index, texturing_mode, cache, output);
|
||||
} break;
|
||||
@ -1281,7 +1282,7 @@ void build_transition_mesh(const VoxelBuffer &voxels, unsigned int sdf_channel,
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
// From this point, we expect the buffer to contain allocated data in the relevant channels.
|
||||
|
||||
ArraySlice<uint8_t> sdf_data_raw;
|
||||
Span<uint8_t> sdf_data_raw;
|
||||
CRASH_COND(voxels.get_channel_raw(sdf_channel, sdf_data_raw) == false);
|
||||
|
||||
const unsigned int voxels_count = voxels.get_size().volume();
|
||||
@ -1330,19 +1331,19 @@ void build_transition_mesh(const VoxelBuffer &voxels, unsigned int sdf_channel,
|
||||
|
||||
switch (voxels.get_channel_depth(sdf_channel)) {
|
||||
case VoxelBuffer::DEPTH_8_BIT: {
|
||||
ArraySlice<const uint8_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint8_t>();
|
||||
Span<const uint8_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint8_t>();
|
||||
build_transition_mesh<uint8_t>(sdf_data, indices_data, weights_data,
|
||||
voxels.get_size(), direction, lod_index, texturing_mode, cache, output);
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::DEPTH_16_BIT: {
|
||||
ArraySlice<const uint16_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint16_t>();
|
||||
Span<const uint16_t> sdf_data = sdf_data_raw.reinterpret_cast_to<const uint16_t>();
|
||||
build_transition_mesh<uint16_t>(sdf_data, indices_data, weights_data,
|
||||
voxels.get_size(), direction, lod_index, texturing_mode, cache, output);
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::DEPTH_32_BIT: {
|
||||
ArraySlice<const float> sdf_data = sdf_data_raw.reinterpret_cast_to<const float>();
|
||||
Span<const float> sdf_data = sdf_data_raw.reinterpret_cast_to<const float>();
|
||||
build_transition_mesh<float>(sdf_data, indices_data, weights_data,
|
||||
voxels.get_size(), direction, lod_index, texturing_mode, cache, output);
|
||||
} break;
|
||||
|
@ -226,7 +226,6 @@ static inline Vector3i get_block_center(Vector3i pos, int bs, int lod) {
|
||||
|
||||
void VoxelServer::init_priority_dependency(
|
||||
VoxelServer::PriorityDependency &dep, Vector3i block_position, uint8_t lod, const Volume &volume, int block_size) {
|
||||
|
||||
const Vector3i voxel_pos = get_block_center(block_position, block_size, lod);
|
||||
const float block_radius = (block_size << lod) / 2;
|
||||
dep.shared = _world.shared_priority_dependency;
|
||||
@ -335,7 +334,6 @@ void VoxelServer::request_voxel_block_save(uint32_t volume_id, Ref<VoxelBuffer>
|
||||
|
||||
void VoxelServer::request_instance_block_save(uint32_t volume_id, std::unique_ptr<VoxelInstanceBlockData> 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);
|
||||
@ -548,7 +546,6 @@ void VoxelServer::process() {
|
||||
// The request response must match the dependency it would have been requested with.
|
||||
// If it doesn't match, we are no longer interested in the result.
|
||||
if (volume->meshing_dependency == r->meshing_dependency) {
|
||||
|
||||
BlockMeshOutput o;
|
||||
// TODO Check for invalidation due to property changes
|
||||
|
||||
@ -678,8 +675,8 @@ void VoxelServer::BlockDataRequest::run(VoxelTaskContext ctx) {
|
||||
instance_data_request.position = position;
|
||||
VoxelStream::Result instances_result;
|
||||
stream->load_instance_blocks(
|
||||
ArraySlice<VoxelStreamInstanceDataRequest>(&instance_data_request, 1),
|
||||
ArraySlice<VoxelStream::Result>(&instances_result, 1));
|
||||
Span<VoxelStreamInstanceDataRequest>(&instance_data_request, 1),
|
||||
Span<VoxelStream::Result>(&instances_result, 1));
|
||||
|
||||
if (instances_result == VoxelStream::RESULT_ERROR) {
|
||||
ERR_PRINT("Error loading instance block");
|
||||
@ -717,7 +714,7 @@ void VoxelServer::BlockDataRequest::run(VoxelTaskContext ctx) {
|
||||
instance_data_request.lod = lod;
|
||||
instance_data_request.position = position;
|
||||
instance_data_request.data = std::move(instances);
|
||||
stream->save_instance_blocks(ArraySlice<VoxelStreamInstanceDataRequest>(&instance_data_request, 1));
|
||||
stream->save_instance_blocks(Span<VoxelStreamInstanceDataRequest>(&instance_data_request, 1));
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -787,9 +784,8 @@ bool VoxelServer::BlockGenerateRequest::is_cancelled() {
|
||||
// Takes a list of blocks and interprets it as a cube of blocks centered around the area we want to create a mesh from.
|
||||
// Voxels from central blocks are copied, and part of side blocks are also copied so we get a temporary buffer
|
||||
// which includes enough neighbors for the mesher to avoid doing bound checks.
|
||||
static void copy_block_and_neighbors(ArraySlice<Ref<VoxelBuffer> > blocks, VoxelBuffer &dst,
|
||||
static void copy_block_and_neighbors(Span<Ref<VoxelBuffer>> blocks, VoxelBuffer &dst,
|
||||
int min_padding, int max_padding, int channels_mask) {
|
||||
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
// Extract wanted channels in a list
|
||||
@ -876,7 +872,7 @@ void VoxelServer::BlockMeshRequest::run(VoxelTaskContext ctx) {
|
||||
// TODO Cache?
|
||||
Ref<VoxelBuffer> voxels;
|
||||
voxels.instance();
|
||||
copy_block_and_neighbors(to_slice(blocks, blocks_count),
|
||||
copy_block_and_neighbors(to_span(blocks, blocks_count),
|
||||
**voxels, min_padding, max_padding, mesher->get_used_channels_mask());
|
||||
|
||||
VoxelMesher::Input input = { **voxels, lod };
|
||||
|
@ -94,7 +94,7 @@ void VoxelThreadPool::enqueue(IVoxelTask *task) {
|
||||
_tasks_semaphore.post();
|
||||
}
|
||||
|
||||
void VoxelThreadPool::enqueue(ArraySlice<IVoxelTask *> tasks) {
|
||||
void VoxelThreadPool::enqueue(Span<IVoxelTask *> tasks) {
|
||||
{
|
||||
MutexLock lock(_tasks_mutex);
|
||||
for (size_t i = 0; i < tasks.size(); ++i) {
|
||||
|
@ -2,8 +2,8 @@
|
||||
#define VOXEL_THREAD_POOL_H
|
||||
|
||||
#include "../storage/voxel_buffer.h"
|
||||
#include "../util/array_slice.h"
|
||||
#include "../util/fixed_array.h"
|
||||
#include "../util/span.h"
|
||||
#include <core/os/mutex.h>
|
||||
#include <core/os/semaphore.h>
|
||||
#include <core/os/thread.h>
|
||||
@ -63,7 +63,7 @@ public:
|
||||
// Schedules a task.
|
||||
// Ownership is NOT passed to the pool, so make sure you get them back when completed if you want to delete them.
|
||||
void enqueue(IVoxelTask *task);
|
||||
void enqueue(ArraySlice<IVoxelTask *> tasks);
|
||||
void enqueue(Span<IVoxelTask *> tasks);
|
||||
|
||||
// TODO Lambda might not be the best API. memcpying to a vector would ensure we lock for a shorter time.
|
||||
template <typename F>
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include "../util/math/rect3i.h"
|
||||
|
||||
void copy_3d_region_zxy(
|
||||
ArraySlice<uint8_t> dst, Vector3i dst_size, Vector3i dst_min,
|
||||
ArraySlice<const uint8_t> src, Vector3i src_size, Vector3i src_min, Vector3i src_max,
|
||||
Span<uint8_t> dst, Vector3i dst_size, Vector3i dst_min,
|
||||
Span<const uint8_t> src, Vector3i src_size, Vector3i src_min, Vector3i src_max,
|
||||
size_t item_size) {
|
||||
//
|
||||
Vector3i::sort_min_max(src_min, src_max);
|
||||
|
@ -2,8 +2,8 @@
|
||||
#define VOXEL_STORAGE_FUNCS_H
|
||||
|
||||
#include "../constants/voxel_constants.h"
|
||||
#include "../util/array_slice.h"
|
||||
#include "../util/math/vector3i.h"
|
||||
#include "../util/span.h"
|
||||
#include <stdint.h>
|
||||
|
||||
inline void clip_copy_region_coord(int &src_min, int &src_max, const int src_size, int &dst_min, const int dst_size) {
|
||||
@ -39,14 +39,14 @@ inline void clip_copy_region(
|
||||
}
|
||||
|
||||
void copy_3d_region_zxy(
|
||||
ArraySlice<uint8_t> dst, Vector3i dst_size, Vector3i dst_min,
|
||||
ArraySlice<const uint8_t> src, Vector3i src_size, Vector3i src_min, Vector3i src_max,
|
||||
Span<uint8_t> dst, Vector3i dst_size, Vector3i dst_min,
|
||||
Span<const uint8_t> src, Vector3i src_size, Vector3i src_min, Vector3i src_max,
|
||||
size_t item_size);
|
||||
|
||||
template <typename T>
|
||||
inline void copy_3d_region_zxy(
|
||||
ArraySlice<T> dst, Vector3i dst_size, Vector3i dst_min,
|
||||
ArraySlice<const T> src, Vector3i src_size, Vector3i src_min, Vector3i src_max) {
|
||||
Span<T> dst, Vector3i dst_size, Vector3i dst_min,
|
||||
Span<const T> src, Vector3i src_size, Vector3i src_min, Vector3i src_max) {
|
||||
// The `template` keyword before method name is required when compiling with GCC
|
||||
copy_3d_region_zxy(
|
||||
dst.template reinterpret_cast_to<uint8_t>(), dst_size, dst_min,
|
||||
@ -55,7 +55,7 @@ inline void copy_3d_region_zxy(
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void fill_3d_region_zxy(ArraySlice<T> dst, Vector3i dst_size, Vector3i dst_min, Vector3i dst_max, const T value) {
|
||||
void fill_3d_region_zxy(Span<T> dst, Vector3i dst_size, Vector3i dst_min, Vector3i dst_max, const T value) {
|
||||
Vector3i::sort_min_max(dst_min, dst_max);
|
||||
dst_min.x = clamp(dst_min.x, 0, dst_size.x);
|
||||
dst_min.y = clamp(dst_min.y, 0, dst_size.y);
|
||||
|
@ -520,8 +520,8 @@ void VoxelBuffer::copy_from(const VoxelBuffer &other, Vector3i src_min, Vector3i
|
||||
create_channel(channel_index, _size, channel.defval);
|
||||
}
|
||||
const unsigned int item_size = get_depth_byte_count(channel.depth);
|
||||
ArraySlice<const uint8_t> src(other_channel.data, other_channel.size_in_bytes);
|
||||
ArraySlice<uint8_t> dst(channel.data, channel.size_in_bytes);
|
||||
Span<const uint8_t> src(other_channel.data, other_channel.size_in_bytes);
|
||||
Span<uint8_t> dst(channel.data, channel.size_in_bytes);
|
||||
copy_3d_region_zxy(dst, _size, dst_min, src, other._size, src_min, src_max, item_size);
|
||||
|
||||
} else if (channel.defval != other_channel.defval) {
|
||||
@ -551,13 +551,13 @@ Ref<VoxelBuffer> VoxelBuffer::duplicate(bool include_metadata) const {
|
||||
return Ref<VoxelBuffer>(d);
|
||||
}
|
||||
|
||||
bool VoxelBuffer::get_channel_raw(unsigned int channel_index, ArraySlice<uint8_t> &slice) const {
|
||||
bool VoxelBuffer::get_channel_raw(unsigned int channel_index, Span<uint8_t> &slice) const {
|
||||
const Channel &channel = _channels[channel_index];
|
||||
if (channel.data != nullptr) {
|
||||
slice = ArraySlice<uint8_t>(channel.data, 0, channel.size_in_bytes);
|
||||
slice = Span<uint8_t>(channel.data, 0, channel.size_in_bytes);
|
||||
return true;
|
||||
}
|
||||
slice = ArraySlice<uint8_t>();
|
||||
slice = Span<uint8_t>();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
#define VOXEL_BUFFER_H
|
||||
|
||||
#include "../constants/voxel_constants.h"
|
||||
#include "../util/array_slice.h"
|
||||
#include "../util/fixed_array.h"
|
||||
#include "../util/math/rect3i.h"
|
||||
#include "../util/span.h"
|
||||
#include "funcs.h"
|
||||
|
||||
#include <core/map.h>
|
||||
@ -148,7 +148,7 @@ public:
|
||||
// `src_min` and `src_max` are the sub-region of that box we want to copy.
|
||||
// `dst_min` is the lower corner where we want the data to be copied into the destination.
|
||||
template <typename T>
|
||||
void copy_from(ArraySlice<const T> src, Vector3i src_size, Vector3i src_min, Vector3i src_max, Vector3i dst_min,
|
||||
void copy_from(Span<const T> src, Vector3i src_size, Vector3i src_min, Vector3i src_max, Vector3i dst_min,
|
||||
unsigned int channel_index) {
|
||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
||||
|
||||
@ -163,7 +163,7 @@ public:
|
||||
// or schedule a recompression for later.
|
||||
decompress_channel(channel_index);
|
||||
|
||||
ArraySlice<T> dst(static_cast<T *>(channel.data), channel.size_in_bytes / sizeof(T));
|
||||
Span<T> dst(static_cast<T *>(channel.data), channel.size_in_bytes / sizeof(T));
|
||||
copy_3d_region_zxy<T>(dst, _size, dst_min, src, src_size, src_min, src_max);
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ public:
|
||||
// `dst_min` is the lower corner of where we want the source data to be stored.
|
||||
// `src_min` and `src_max` is the sub-region of the source we want to copy.
|
||||
template <typename T>
|
||||
void copy_to(ArraySlice<T> dst, Vector3i dst_size, Vector3i dst_min, Vector3i src_min, Vector3i src_max,
|
||||
void copy_to(Span<T> dst, Vector3i dst_size, Vector3i dst_min, Vector3i src_min, Vector3i src_max,
|
||||
unsigned int channel_index) const {
|
||||
ERR_FAIL_INDEX(channel_index, MAX_CHANNELS);
|
||||
|
||||
@ -187,7 +187,7 @@ public:
|
||||
if (channel.data == nullptr) {
|
||||
fill_3d_region_zxy<T>(dst, dst_size, dst_min, dst_min + (src_max - src_min), channel.defval);
|
||||
} else {
|
||||
ArraySlice<const T> src(static_cast<const T *>(channel.data), channel.size_in_bytes / sizeof(T));
|
||||
Span<const T> src(static_cast<const T *>(channel.data), channel.size_in_bytes / sizeof(T));
|
||||
copy_3d_region_zxy<T>(dst, dst_size, dst_min, src, _size, src_min, src_max);
|
||||
}
|
||||
}
|
||||
@ -253,8 +253,8 @@ public:
|
||||
ERR_FAIL_COND(!Rect3i(Vector3i(), _size).contains(box));
|
||||
ERR_FAIL_COND(get_depth_byte_count(channel.depth) != sizeof(Data_T));
|
||||
#endif
|
||||
ArraySlice<Data_T> data = ArraySlice<uint8_t>(channel.data, channel.size_in_bytes)
|
||||
.reinterpret_cast_to<Data_T>();
|
||||
Span<Data_T> data = Span<uint8_t>(channel.data, channel.size_in_bytes)
|
||||
.reinterpret_cast_to<Data_T>();
|
||||
for_each_index_and_pos(box, [data, action_func, offset](unsigned int i, Vector3i pos) {
|
||||
data[i] = action_func(pos + offset, data[i]);
|
||||
});
|
||||
@ -273,10 +273,10 @@ public:
|
||||
ERR_FAIL_COND(get_depth_byte_count(channel0.depth) != sizeof(Data0_T));
|
||||
ERR_FAIL_COND(get_depth_byte_count(channel1.depth) != sizeof(Data1_T));
|
||||
#endif
|
||||
ArraySlice<Data0_T> data0 = ArraySlice<uint8_t>(channel0.data, channel0.size_in_bytes)
|
||||
.reinterpret_cast_to<Data0_T>();
|
||||
ArraySlice<Data1_T> data1 = ArraySlice<uint8_t>(channel1.data, channel1.size_in_bytes)
|
||||
.reinterpret_cast_to<Data1_T>();
|
||||
Span<Data0_T> data0 = Span<uint8_t>(channel0.data, channel0.size_in_bytes)
|
||||
.reinterpret_cast_to<Data0_T>();
|
||||
Span<Data1_T> data1 = Span<uint8_t>(channel1.data, channel1.size_in_bytes)
|
||||
.reinterpret_cast_to<Data1_T>();
|
||||
for_each_index_and_pos(box, [action_func, offset, &data0, &data1](unsigned int i, Vector3i pos) {
|
||||
// TODO The caller must still specify exactly the correct type, maybe some conversion could be used
|
||||
action_func(pos + offset, data0[i], data1[i]);
|
||||
@ -375,7 +375,7 @@ public:
|
||||
}
|
||||
|
||||
// TODO Have a template version based on channel depth
|
||||
bool get_channel_raw(unsigned int channel_index, ArraySlice<uint8_t> &slice) const;
|
||||
bool get_channel_raw(unsigned int channel_index, Span<uint8_t> &slice) const;
|
||||
|
||||
void downscale_to(VoxelBuffer &dst, Vector3i src_min, Vector3i src_max, Vector3i dst_min) const;
|
||||
Ref<VoxelTool> get_voxel_tool();
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
namespace VoxelCompressedData {
|
||||
|
||||
bool decompress(ArraySlice<const uint8_t> src, std::vector<uint8_t> &dst) {
|
||||
bool decompress(Span<const uint8_t> src, std::vector<uint8_t> &dst) {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
// TODO Apparently big-endian is dead
|
||||
@ -56,7 +56,7 @@ bool decompress(ArraySlice<const uint8_t> src, std::vector<uint8_t> &dst) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compress(ArraySlice<const uint8_t> src, std::vector<uint8_t> &dst, Compression comp) {
|
||||
bool compress(Span<const uint8_t> src, std::vector<uint8_t> &dst, Compression comp) {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
switch (comp) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef VOXEL_COMPRESSED_DATA_H
|
||||
#define VOXEL_COMPRESSED_DATA_H
|
||||
|
||||
#include "../util/array_slice.h"
|
||||
#include "../util/span.h"
|
||||
|
||||
namespace VoxelCompressedData {
|
||||
|
||||
@ -19,8 +19,8 @@ enum Compression {
|
||||
COMPRESSION_COUNT = 2
|
||||
};
|
||||
|
||||
bool compress(ArraySlice<const uint8_t> src, std::vector<uint8_t> &dst, Compression comp);
|
||||
bool decompress(ArraySlice<const uint8_t> src, std::vector<uint8_t> &dst);
|
||||
bool compress(Span<const uint8_t> src, std::vector<uint8_t> &dst, Compression comp);
|
||||
bool decompress(Span<const uint8_t> src, std::vector<uint8_t> &dst);
|
||||
|
||||
} // namespace VoxelCompressedData
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "instance_data.h"
|
||||
#include "../constants/voxel_constants.h"
|
||||
#include "../util/array_slice.h"
|
||||
#include "../util/math/funcs.h"
|
||||
#include "../util/serialization.h"
|
||||
#include <core/variant.h>
|
||||
@ -94,7 +93,7 @@ void serialize_instance_block_data(const VoxelInstanceBlockData &src, std::vecto
|
||||
w.store_32(TRAILING_MAGIC);
|
||||
}
|
||||
|
||||
bool deserialize_instance_block_data(VoxelInstanceBlockData &dst, ArraySlice<const uint8_t> src) {
|
||||
bool deserialize_instance_block_data(VoxelInstanceBlockData &dst, Span<const uint8_t> src) {
|
||||
const uint8_t expected_version = 0;
|
||||
const uint8_t expected_instance_format = 0;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef VOXEL_INSTANCE_DATA_H
|
||||
#define VOXEL_INSTANCE_DATA_H
|
||||
|
||||
#include "../util/array_slice.h"
|
||||
#include "../util/span.h"
|
||||
#include <core/math/transform.h>
|
||||
|
||||
// Stores data to pass around until it either gets saved or turned into actual instances
|
||||
@ -27,6 +27,6 @@ struct VoxelInstanceBlockData {
|
||||
};
|
||||
|
||||
void serialize_instance_block_data(const VoxelInstanceBlockData &src, std::vector<uint8_t> &dst);
|
||||
bool deserialize_instance_block_data(VoxelInstanceBlockData &dst, ArraySlice<const uint8_t> src);
|
||||
bool deserialize_instance_block_data(VoxelInstanceBlockData &dst, Span<const uint8_t> src);
|
||||
|
||||
#endif // VOXEL_INSTANCE_DATA_H
|
||||
|
@ -333,7 +333,6 @@ bool VoxelStreamSQLiteInternal::save_block(BlockLocation loc, const std::vector<
|
||||
|
||||
VoxelStream::Result VoxelStreamSQLiteInternal::load_block(
|
||||
BlockLocation loc, std::vector<uint8_t> &out_block_data, BlockType type) {
|
||||
|
||||
sqlite3 *db = _db;
|
||||
|
||||
sqlite3_stmt *get_block_statement;
|
||||
@ -681,8 +680,7 @@ bool VoxelStreamSQLite::supports_instance_blocks() const {
|
||||
}
|
||||
|
||||
void VoxelStreamSQLite::load_instance_blocks(
|
||||
ArraySlice<VoxelStreamInstanceDataRequest> out_blocks, ArraySlice<Result> out_results) {
|
||||
|
||||
Span<VoxelStreamInstanceDataRequest> out_blocks, Span<Result> out_results) {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
// TODO Get block size from database
|
||||
@ -726,13 +724,13 @@ void VoxelStreamSQLite::load_instance_blocks(
|
||||
const Result res = con->load_block(loc, _temp_compressed_block_data, VoxelStreamSQLiteInternal::INSTANCES);
|
||||
|
||||
if (res == RESULT_BLOCK_FOUND) {
|
||||
if (!VoxelCompressedData::decompress(to_slice_const(_temp_compressed_block_data), _temp_block_data)) {
|
||||
if (!VoxelCompressedData::decompress(to_span_const(_temp_compressed_block_data), _temp_block_data)) {
|
||||
ERR_PRINT("Failed to decompress instance block");
|
||||
out_results[i] = RESULT_ERROR;
|
||||
continue;
|
||||
}
|
||||
r.data = std::make_unique<VoxelInstanceBlockData>();
|
||||
if (!deserialize_instance_block_data(*r.data, to_slice_const(_temp_block_data))) {
|
||||
if (!deserialize_instance_block_data(*r.data, to_span_const(_temp_block_data))) {
|
||||
ERR_PRINT("Failed to deserialize instance block");
|
||||
out_results[i] = RESULT_ERROR;
|
||||
continue;
|
||||
@ -747,7 +745,7 @@ void VoxelStreamSQLite::load_instance_blocks(
|
||||
recycle_connection(con);
|
||||
}
|
||||
|
||||
void VoxelStreamSQLite::save_instance_blocks(ArraySlice<VoxelStreamInstanceDataRequest> p_blocks) {
|
||||
void VoxelStreamSQLite::save_instance_blocks(Span<VoxelStreamInstanceDataRequest> p_blocks) {
|
||||
// TODO Get block size from database
|
||||
//const int bs_po2 = VoxelConstants::DEFAULT_BLOCK_SIZE_PO2;
|
||||
|
||||
@ -814,7 +812,7 @@ void VoxelStreamSQLite::flush_cache(VoxelStreamSQLiteInternal *con) {
|
||||
serialize_instance_block_data(*block.instances, temp_data);
|
||||
|
||||
ERR_FAIL_COND(!VoxelCompressedData::compress(
|
||||
to_slice_const(temp_data), temp_compressed_data, VoxelCompressedData::COMPRESSION_NONE));
|
||||
to_span_const(temp_data), temp_compressed_data, VoxelCompressedData::COMPRESSION_NONE));
|
||||
}
|
||||
con->save_block(loc, temp_compressed_data, VoxelStreamSQLiteInternal::INSTANCES);
|
||||
|
||||
|
@ -29,8 +29,8 @@ public:
|
||||
|
||||
bool supports_instance_blocks() const override;
|
||||
void load_instance_blocks(
|
||||
ArraySlice<VoxelStreamInstanceDataRequest> out_blocks, ArraySlice<Result> out_results) override;
|
||||
void save_instance_blocks(ArraySlice<VoxelStreamInstanceDataRequest> p_blocks) override;
|
||||
Span<VoxelStreamInstanceDataRequest> out_blocks, Span<Result> out_results) override;
|
||||
void save_instance_blocks(Span<VoxelStreamInstanceDataRequest> p_blocks) override;
|
||||
|
||||
void flush_cache();
|
||||
|
||||
|
@ -125,14 +125,14 @@ Error VoxelVoxLoader::load_from_file(String fpath, Ref<VoxelBuffer> voxels, Ref<
|
||||
|
||||
const VoxelBuffer::ChannelId channel = VoxelBuffer::CHANNEL_COLOR;
|
||||
|
||||
const ArraySlice<Color8> src_palette =
|
||||
const Span<Color8> src_palette =
|
||||
_data.has_palette ?
|
||||
ArraySlice<Color8>(_data.palette) :
|
||||
ArraySlice<Color8>(reinterpret_cast<Color8 *>(vox::g_default_palette), 0, vox::PALETTE_SIZE);
|
||||
Span<Color8>(_data.palette) :
|
||||
Span<Color8>(reinterpret_cast<Color8 *>(vox::g_default_palette), 0, vox::PALETTE_SIZE);
|
||||
|
||||
const VoxelBuffer::Depth depth = voxels->get_channel_depth(VoxelBuffer::CHANNEL_COLOR);
|
||||
|
||||
ArraySlice<uint8_t> dst_raw;
|
||||
Span<uint8_t> dst_raw;
|
||||
voxels->create(_data.size);
|
||||
voxels->decompress_channel(channel);
|
||||
CRASH_COND(!voxels->get_channel_raw(channel, dst_raw));
|
||||
@ -148,7 +148,7 @@ Error VoxelVoxLoader::load_from_file(String fpath, Ref<VoxelBuffer> voxels, Ref<
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::DEPTH_16_BIT: {
|
||||
ArraySlice<uint16_t> dst = dst_raw.reinterpret_cast_to<uint16_t>();
|
||||
Span<uint16_t> dst = dst_raw.reinterpret_cast_to<uint16_t>();
|
||||
for (size_t i = 0; i < dst.size(); ++i) {
|
||||
dst[i] = _data.color_indexes[i];
|
||||
}
|
||||
@ -169,7 +169,7 @@ Error VoxelVoxLoader::load_from_file(String fpath, Ref<VoxelBuffer> voxels, Ref<
|
||||
} break;
|
||||
|
||||
case VoxelBuffer::DEPTH_16_BIT: {
|
||||
ArraySlice<uint16_t> dst = dst_raw.reinterpret_cast_to<uint16_t>();
|
||||
Span<uint16_t> dst = dst_raw.reinterpret_cast_to<uint16_t>();
|
||||
for (size_t i = 0; i < dst.size(); ++i) {
|
||||
const uint8_t ci = _data.color_indexes[i];
|
||||
dst[i] = src_palette[ci].to_u16();
|
||||
|
@ -215,7 +215,7 @@ VoxelBlockSerializerInternal::SerializeResult VoxelBlockSerializerInternal::seri
|
||||
|
||||
switch (compression) {
|
||||
case VoxelBuffer::COMPRESSION_NONE: {
|
||||
ArraySlice<uint8_t> data;
|
||||
Span<uint8_t> data;
|
||||
ERR_FAIL_COND_V(!voxel_buffer.get_channel_raw(channel_index, data), SerializeResult(_data, false));
|
||||
f->store_buffer(data.data(), data.size());
|
||||
} break;
|
||||
@ -310,7 +310,7 @@ bool VoxelBlockSerializerInternal::deserialize(const std::vector<uint8_t> &p_dat
|
||||
case VoxelBuffer::COMPRESSION_NONE: {
|
||||
out_voxel_buffer.decompress_channel(channel_index);
|
||||
|
||||
ArraySlice<uint8_t> buffer;
|
||||
Span<uint8_t> buffer;
|
||||
CRASH_COND(!out_voxel_buffer.get_channel_raw(channel_index, buffer));
|
||||
|
||||
const uint32_t read_len = f->get_buffer(buffer.data(), buffer.size());
|
||||
@ -363,7 +363,6 @@ bool VoxelBlockSerializerInternal::deserialize(const std::vector<uint8_t> &p_dat
|
||||
|
||||
VoxelBlockSerializerInternal::SerializeResult VoxelBlockSerializerInternal::serialize_and_compress(
|
||||
const VoxelBuffer &voxel_buffer) {
|
||||
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
SerializeResult res = serialize(voxel_buffer);
|
||||
@ -371,7 +370,7 @@ VoxelBlockSerializerInternal::SerializeResult VoxelBlockSerializerInternal::seri
|
||||
const std::vector<uint8_t> &data = res.data;
|
||||
|
||||
res.success = VoxelCompressedData::compress(
|
||||
ArraySlice<const uint8_t>(data.data(), 0, data.size()), _compressed_data,
|
||||
Span<const uint8_t>(data.data(), 0, data.size()), _compressed_data,
|
||||
VoxelCompressedData::COMPRESSION_LZ4);
|
||||
ERR_FAIL_COND_V(!res.success, SerializeResult(_compressed_data, false));
|
||||
|
||||
@ -380,10 +379,9 @@ VoxelBlockSerializerInternal::SerializeResult VoxelBlockSerializerInternal::seri
|
||||
|
||||
bool VoxelBlockSerializerInternal::decompress_and_deserialize(
|
||||
const std::vector<uint8_t> &p_data, VoxelBuffer &out_voxel_buffer) {
|
||||
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
const bool res = VoxelCompressedData::decompress(ArraySlice<const uint8_t>(p_data.data(), 0, p_data.size()), _data);
|
||||
const bool res = VoxelCompressedData::decompress(Span<const uint8_t>(p_data.data(), 0, p_data.size()), _data);
|
||||
ERR_FAIL_COND_V(!res, false);
|
||||
|
||||
return deserialize(_data, out_voxel_buffer);
|
||||
@ -424,7 +422,6 @@ int VoxelBlockSerializerInternal::serialize(Ref<StreamPeer> peer, Ref<VoxelBuffe
|
||||
|
||||
void VoxelBlockSerializerInternal::deserialize(
|
||||
Ref<StreamPeer> peer, Ref<VoxelBuffer> voxel_buffer, int size, bool decompress) {
|
||||
|
||||
if (decompress) {
|
||||
_compressed_data.resize(size);
|
||||
const Error err = peer->get_data(_compressed_data.data(), _compressed_data.size());
|
||||
|
@ -40,14 +40,14 @@ bool VoxelStream::supports_instance_blocks() const {
|
||||
}
|
||||
|
||||
void VoxelStream::load_instance_blocks(
|
||||
ArraySlice<VoxelStreamInstanceDataRequest> out_blocks, ArraySlice<Result> out_results) {
|
||||
Span<VoxelStreamInstanceDataRequest> out_blocks, Span<Result> out_results) {
|
||||
// Can be implemented in subclasses
|
||||
for (size_t i = 0; i < out_results.size(); ++i) {
|
||||
out_results[i] = RESULT_BLOCK_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelStream::save_instance_blocks(ArraySlice<VoxelStreamInstanceDataRequest> p_blocks) {
|
||||
void VoxelStream::save_instance_blocks(Span<VoxelStreamInstanceDataRequest> p_blocks) {
|
||||
// Can be implemented in subclasses
|
||||
}
|
||||
|
||||
|
@ -43,12 +43,12 @@ public:
|
||||
virtual void immerge_block(Ref<VoxelBuffer> buffer, Vector3i origin_in_voxels, int lod);
|
||||
|
||||
// TODO Rename load_voxel_blocks
|
||||
// TODO Pass with ArraySlice
|
||||
// TODO Pass with Span
|
||||
// Note: vector is passed by ref for performance. Don't reorder it.
|
||||
virtual void emerge_blocks(Vector<VoxelBlockRequest> &p_blocks, Vector<Result> &out_results);
|
||||
|
||||
// TODO Rename save_voxel_blocks
|
||||
// TODO Pass with ArraySlice
|
||||
// TODO Pass with Span
|
||||
// Returns multiple blocks of voxels to the stream.
|
||||
// This function is recommended if you save to files, because you can batch their access.
|
||||
virtual void immerge_blocks(const Vector<VoxelBlockRequest> &p_blocks);
|
||||
@ -56,9 +56,9 @@ public:
|
||||
virtual bool supports_instance_blocks() const;
|
||||
|
||||
virtual void load_instance_blocks(
|
||||
ArraySlice<VoxelStreamInstanceDataRequest> out_blocks, ArraySlice<Result> out_results);
|
||||
Span<VoxelStreamInstanceDataRequest> out_blocks, Span<Result> out_results);
|
||||
|
||||
virtual void save_instance_blocks(ArraySlice<VoxelStreamInstanceDataRequest> p_blocks);
|
||||
virtual void save_instance_blocks(Span<VoxelStreamInstanceDataRequest> p_blocks);
|
||||
|
||||
// Tells which channels can be found in this stream.
|
||||
// The simplest implementation is to return them all.
|
||||
|
@ -487,7 +487,7 @@ void VoxelInstancer::regenerate_layer(uint16_t layer_id, bool regenerate_blocks)
|
||||
// We may setup a local transform list as well since it's expensive to get it from VisualServer
|
||||
}
|
||||
|
||||
update_block_from_transforms(block_index, to_slice_const(_transform_cache),
|
||||
update_block_from_transforms(block_index, to_span_const(_transform_cache),
|
||||
block->grid_position, layer, *item, layer_id, world, block_transform);
|
||||
}
|
||||
}
|
||||
@ -646,7 +646,6 @@ void VoxelInstancer::remove_block(unsigned int block_index) {
|
||||
|
||||
void VoxelInstancer::on_data_block_loaded(Vector3i grid_position, unsigned int lod_index,
|
||||
std::unique_ptr<VoxelInstanceBlockData> 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)));
|
||||
@ -727,10 +726,9 @@ int VoxelInstancer::create_block(Layer *layer, uint16_t layer_id, Vector3i grid_
|
||||
return block_index;
|
||||
}
|
||||
|
||||
void VoxelInstancer::update_block_from_transforms(int block_index, ArraySlice<const Transform> transforms,
|
||||
void VoxelInstancer::update_block_from_transforms(int block_index, Span<const Transform> transforms,
|
||||
Vector3i grid_position, Layer *layer, const VoxelInstanceLibraryItem *item, uint16_t layer_id,
|
||||
World *world, const Transform &block_transform) {
|
||||
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
CRASH_COND(layer == nullptr);
|
||||
@ -946,7 +944,7 @@ void VoxelInstancer::create_render_blocks(Vector3i render_grid_position, int lod
|
||||
}
|
||||
}
|
||||
|
||||
update_block_from_transforms(-1, to_slice_const(_transform_cache),
|
||||
update_block_from_transforms(-1, to_span_const(_transform_cache),
|
||||
render_grid_position, layer, item, layer_id, world, block_transform);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define VOXEL_INSTANCER_H
|
||||
|
||||
#include "../../streams/instance_data.h"
|
||||
#include "../../util/array_slice.h"
|
||||
#include "../../util/fixed_array.h"
|
||||
#include "../../util/godot/direct_multimesh_instance.h"
|
||||
#include "../../util/math/rect3i.h"
|
||||
@ -93,7 +92,7 @@ private:
|
||||
|
||||
void create_render_blocks(Vector3i grid_position, int lod_index, Array surface_arrays);
|
||||
|
||||
void update_block_from_transforms(int block_index, ArraySlice<const Transform> transforms,
|
||||
void update_block_from_transforms(int block_index, Span<const Transform> transforms,
|
||||
Vector3i grid_position, Layer *layer, const VoxelInstanceLibraryItem *item, uint16_t layer_id,
|
||||
World *world, const Transform &block_transform);
|
||||
|
||||
@ -148,7 +147,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<VoxelInstanceBlockData> > loaded_instances_data;
|
||||
std::unordered_map<Vector3i, std::unique_ptr<VoxelInstanceBlockData>> loaded_instances_data;
|
||||
|
||||
FixedArray<MeshLodDistances, VoxelInstanceLibraryItem::MAX_MESH_LODS> mesh_lod_distances;
|
||||
|
||||
|
@ -221,8 +221,8 @@ void test_copy_3d_region_zxy() {
|
||||
src[i] = i;
|
||||
}
|
||||
|
||||
ArraySlice<const uint16_t> srcs = to_slice_const(src);
|
||||
ArraySlice<uint16_t> dsts = to_slice(dst);
|
||||
Span<const uint16_t> srcs = to_span_const(src);
|
||||
Span<uint16_t> dsts = to_span(dst);
|
||||
const Vector3i dst_min(0, 0, 0);
|
||||
const Vector3i src_min(2, 1, 0);
|
||||
const Vector3i src_max(5, 4, 3);
|
||||
|
@ -86,7 +86,7 @@ void DirectMultiMeshInstance::set_cast_shadows_setting(VisualServer::ShadowCasti
|
||||
vs.instance_geometry_set_cast_shadows_setting(_multimesh_instance, mode);
|
||||
}
|
||||
|
||||
PoolRealArray DirectMultiMeshInstance::make_transform_3d_bulk_array(ArraySlice<const Transform> transforms) {
|
||||
PoolRealArray DirectMultiMeshInstance::make_transform_3d_bulk_array(Span<const Transform> transforms) {
|
||||
VOXEL_PROFILE_SCOPE();
|
||||
|
||||
PoolRealArray bulk_array;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef DIRECT_MULTIMESH_INSTANCE_H
|
||||
#define DIRECT_MULTIMESH_INSTANCE_H
|
||||
|
||||
#include "../array_slice.h"
|
||||
#include "../span.h"
|
||||
|
||||
#include <core/rid.h>
|
||||
#include <scene/resources/multimesh.h>
|
||||
@ -25,7 +25,7 @@ public:
|
||||
void set_material_override(Ref<Material> material);
|
||||
void set_cast_shadows_setting(VisualServer::ShadowCastingSetting mode);
|
||||
|
||||
static PoolRealArray make_transform_3d_bulk_array(ArraySlice<const Transform> transforms);
|
||||
static PoolRealArray make_transform_3d_bulk_array(Span<const Transform> transforms);
|
||||
|
||||
private:
|
||||
RID _multimesh_instance;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef VOXEL_UTIL_SERIALIZATION_H
|
||||
#define VOXEL_UTIL_SERIALIZATION_H
|
||||
|
||||
#include "array_slice.h"
|
||||
#include "span.h"
|
||||
|
||||
namespace VoxelUtility {
|
||||
|
||||
@ -70,12 +70,12 @@ struct MemoryWriter {
|
||||
};
|
||||
|
||||
struct MemoryReader {
|
||||
ArraySlice<const uint8_t> data;
|
||||
Span<const uint8_t> data;
|
||||
size_t pos = 0;
|
||||
// Using network-order by default
|
||||
Endianess endianess = ENDIANESS_BIG_ENDIAN;
|
||||
|
||||
MemoryReader(ArraySlice<const uint8_t> p_data, Endianess p_endianess) :
|
||||
MemoryReader(Span<const uint8_t> p_data, Endianess p_endianess) :
|
||||
data(p_data), endianess(p_endianess) {}
|
||||
|
||||
inline uint8_t get_8() {
|
||||
|
@ -1,31 +1,30 @@
|
||||
#ifndef ARRAY_SLICE_H
|
||||
#define ARRAY_SLICE_H
|
||||
#ifndef SPAN_H
|
||||
#define SPAN_H
|
||||
|
||||
#include "fixed_array.h"
|
||||
#include <core/error_macros.h>
|
||||
#include <vector>
|
||||
|
||||
// TODO Rename Span
|
||||
// View into an array, referencing a pointer and a size.
|
||||
// STL equivalent would be std::span<T> in C++20
|
||||
template <typename T>
|
||||
class ArraySlice {
|
||||
class Span {
|
||||
public:
|
||||
inline ArraySlice() :
|
||||
inline Span() :
|
||||
_ptr(nullptr),
|
||||
_size(0) {
|
||||
}
|
||||
|
||||
inline ArraySlice(T *p_ptr, size_t p_begin, size_t p_end) {
|
||||
inline Span(T *p_ptr, size_t p_begin, size_t p_end) {
|
||||
CRASH_COND(p_end < p_begin);
|
||||
_ptr = p_ptr + p_begin;
|
||||
_size = p_end - p_begin;
|
||||
}
|
||||
|
||||
inline ArraySlice(T *p_ptr, size_t p_size) :
|
||||
inline Span(T *p_ptr, size_t p_size) :
|
||||
_ptr(p_ptr), _size(p_size) {}
|
||||
|
||||
inline ArraySlice(ArraySlice<T> &p_other, size_t p_begin, size_t p_end) {
|
||||
inline Span(Span<T> &p_other, size_t p_begin, size_t p_end) {
|
||||
CRASH_COND(p_end < p_begin);
|
||||
CRASH_COND(p_begin >= p_other.size());
|
||||
CRASH_COND(p_end > p_other.size()); // `>` because p_end is typically `p_begin + size`
|
||||
@ -33,8 +32,8 @@ public:
|
||||
_size = p_end - p_begin;
|
||||
}
|
||||
|
||||
// TODO Remove this one, prefer to_slice() specializations
|
||||
inline ArraySlice(std::vector<T> &vec, size_t p_begin, size_t p_end) {
|
||||
// TODO Remove this one, prefer to_span() specializations
|
||||
inline Span(std::vector<T> &vec, size_t p_begin, size_t p_end) {
|
||||
CRASH_COND(p_end < p_begin);
|
||||
CRASH_COND(p_begin >= vec.size());
|
||||
CRASH_COND(p_end > vec.size()); // `>` because p_end is typically `p_begin + size`
|
||||
@ -42,30 +41,30 @@ public:
|
||||
_size = p_end - p_begin;
|
||||
}
|
||||
|
||||
// TODO Remove this one, prefer to_slice() specializations
|
||||
// TODO Remove this one, prefer to_span() specializations
|
||||
template <unsigned int N>
|
||||
inline ArraySlice(FixedArray<T, N> &a) {
|
||||
inline Span(FixedArray<T, N> &a) {
|
||||
_ptr = a.data();
|
||||
_size = a.size();
|
||||
}
|
||||
|
||||
inline ArraySlice<T> sub(size_t from, size_t len) const {
|
||||
inline Span<T> sub(size_t from, size_t len) const {
|
||||
CRASH_COND(from + len > _size);
|
||||
return ArraySlice<T>(_ptr + from, len);
|
||||
return Span<T>(_ptr + from, len);
|
||||
}
|
||||
|
||||
inline ArraySlice<T> sub(size_t from) const {
|
||||
inline Span<T> sub(size_t from) const {
|
||||
CRASH_COND(from >= _size);
|
||||
return ArraySlice<T>(_ptr + from, _size - from);
|
||||
return Span<T>(_ptr + from, _size - from);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
ArraySlice<U> reinterpret_cast_to() const {
|
||||
Span<U> reinterpret_cast_to() const {
|
||||
const size_t size_in_bytes = _size * sizeof(T);
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(size_in_bytes % sizeof(U) != 0);
|
||||
#endif
|
||||
return ArraySlice<U>(reinterpret_cast<U *>(_ptr), 0, size_in_bytes / sizeof(U));
|
||||
return Span<U>(reinterpret_cast<U *>(_ptr), 0, size_in_bytes / sizeof(U));
|
||||
}
|
||||
|
||||
inline T &operator[](size_t i) {
|
||||
@ -107,35 +106,35 @@ private:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ArraySlice<const T> to_slice(const std::vector<T> &vec) {
|
||||
return ArraySlice<const T>(vec.data(), 0, vec.size());
|
||||
Span<const T> to_span(const std::vector<T> &vec) {
|
||||
return Span<const T>(vec.data(), 0, vec.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ArraySlice<T> to_slice(std::vector<T> &vec) {
|
||||
return ArraySlice<T>(vec.data(), 0, vec.size());
|
||||
Span<T> to_span(std::vector<T> &vec) {
|
||||
return Span<T>(vec.data(), 0, vec.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ArraySlice<const T> to_slice_const(const std::vector<T> &vec) {
|
||||
return ArraySlice<const T>(vec.data(), 0, vec.size());
|
||||
Span<const T> to_span_const(const std::vector<T> &vec) {
|
||||
return Span<const T>(vec.data(), 0, vec.size());
|
||||
}
|
||||
|
||||
template <typename T, unsigned int N>
|
||||
ArraySlice<T> to_slice(FixedArray<T, N> &a, unsigned int count) {
|
||||
Span<T> to_span(FixedArray<T, N> &a, unsigned int count) {
|
||||
CRASH_COND(count > a.size());
|
||||
return ArraySlice<T>(a.data(), count);
|
||||
return Span<T>(a.data(), count);
|
||||
}
|
||||
|
||||
template <typename T, unsigned int N>
|
||||
ArraySlice<const T> to_slice_const(const FixedArray<T, N> &a, unsigned int count) {
|
||||
Span<const T> to_span_const(const FixedArray<T, N> &a, unsigned int count) {
|
||||
CRASH_COND(count > a.size());
|
||||
return ArraySlice<const T>(a.data(), count);
|
||||
return Span<const T>(a.data(), count);
|
||||
}
|
||||
|
||||
template <typename T, unsigned int N>
|
||||
ArraySlice<const T> to_slice_const(const FixedArray<T, N> &a) {
|
||||
return ArraySlice<const T>(a.data(), 0, a.size());
|
||||
Span<const T> to_span_const(const FixedArray<T, N> &a) {
|
||||
return Span<const T>(a.data(), 0, a.size());
|
||||
}
|
||||
|
||||
#endif // ARRAY_SLICE_H
|
||||
#endif // SPAN_H
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
|
||||
<Type Name="ArraySlice<*>">
|
||||
<Type Name="Span<*>">
|
||||
<Expand>
|
||||
<Item Name="[size]">_size</Item>
|
||||
<ArrayItems>
|
||||
|
Loading…
x
Reference in New Issue
Block a user