Renamed ArraySlice -> Span

This commit is contained in:
Marc Gilleron 2021-05-31 16:48:49 +01:00
parent 2e9d817246
commit 411be94559
36 changed files with 219 additions and 236 deletions

View File

@ -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.

View File

@ -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();

View File

@ -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());

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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() {
}

View File

@ -1,6 +1,6 @@
#include "voxel_generator_image.h"
#include "../../util/array_slice.h"
#include "../../util/fixed_array.h"
#include "../../util/span.h"
namespace {

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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 };

View File

@ -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) {

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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());

View File

@ -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
}

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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() {

View File

@ -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

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="ArraySlice&lt;*&gt;">
<Type Name="Span&lt;*&gt;">
<Expand>
<Item Name="[size]">_size</Item>
<ArrayItems>