Skip to content

Commit

Permalink
fixed issue with ring buffer sizes being too small in some cases, add…
Browse files Browse the repository at this point in the history
…ed world grid doc
  • Loading branch information
JungerBoyo authored and JungerBoyo committed Dec 6, 2023
1 parent b0cc52d commit 23d2718
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 150 deletions.
18 changes: 9 additions & 9 deletions src/engine/chunk_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ static void setVertexLayout(u32 vao, u32 vbo) {
glVertexArrayVertexBuffer(vao, vertex_attrib_binding, vbo, 0, sizeof(Vertex));
}

void ChunkPool::init(i32 max_chunks) noexcept {
_chunks_count = max_chunks;

void ChunkPool::init() noexcept {
u32 tmp[3] = { 0U, 0U, 0U };

glCreateBuffers(3, tmp);
Expand All @@ -51,21 +49,21 @@ void ChunkPool::init(i32 max_chunks) noexcept {

glNamedBufferStorage(
_dibo_id,
6 * max_chunks * sizeof(DrawElementsIndirectCmd),
6 * _chunks_count * sizeof(DrawElementsIndirectCmd),
nullptr,
GL_MAP_WRITE_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT
);

_dibo_mapped_ptr = glMapNamedBufferRange(
_dibo_id,
0, 6 * max_chunks * sizeof(DrawElementsIndirectCmd),
0, 6 * _chunks_count * sizeof(DrawElementsIndirectCmd),
GL_MAP_WRITE_BIT|GL_MAP_PERSISTENT_BIT|GL_MAP_COHERENT_BIT
);

try {
_chunks.reserve(max_chunks);
_chunk_id_to_index.resize(max_chunks, INVALID_CHUNK_INDEX);
_voxel_data.resize(static_cast<u64>(max_chunks) * _engine_context.chunk_size_1D);
_chunks.reserve(_chunks_count);
_chunk_id_to_index.resize(_chunks_count, INVALID_CHUNK_INDEX);
_voxel_data.resize(static_cast<u64>(_chunks_count) * _engine_context.chunk_size_1D);
_free_chunks = RingBuffer<FreeChunk>(_chunks_count, {});
_draw_cmds.reserve(_chunks_count * 6);
for (std::size_t i{ 0U }; i < _chunks_count; ++i) {
Expand Down Expand Up @@ -209,7 +207,9 @@ void ChunkPool::recreatePool(MeshingEngine::Result overflow_result) {
const auto max_written_indices_z_axis = std::max(overflow_result.written_indices[Z_POS], overflow_result.written_indices[Z_NEG]);
const auto max_written_indices = std::max(std::max(max_written_indices_x_axis, max_written_indices_y_axis), max_written_indices_z_axis);

auto new_max_vertices_in_submesh = static_cast<u64>(((1.5F * static_cast<f32>(max_written_indices)) / 6.F) * 4.F);
auto new_max_vertices_in_submesh = static_cast<u64>(
((_engine_context.chunk_pool_growth_coefficient * static_cast<f32>(max_written_indices)) / 6.F) * 4.F
);
new_max_vertices_in_submesh = new_max_vertices_in_submesh + (4 - new_max_vertices_in_submesh % 4);

_engine_context.chunk_max_current_submesh_size = new_max_vertices_in_submesh * sizeof(Vertex);
Expand Down
9 changes: 5 additions & 4 deletions src/engine/chunk_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ struct ChunkPool {
////////////////////////////////////

/// @brief count of all chunks in a pool
vmath::i32 _chunks_count;
vmath::u32 _chunks_count;
/// @brief helper array translating chunk_id to its
/// index in <_chunks>
std::vector<vmath::u32> _chunk_id_to_index;
Expand Down Expand Up @@ -158,12 +158,13 @@ struct ChunkPool {

/// @brief meshing engine of the chunk pool. It schedules meshing
/// tasks on the GPU
MeshingEngine _meshing_engine{ _engine_context };
MeshingEngine _meshing_engine{ _engine_context, _chunks_count };

ChunkPool(EngineContext& engine_context) : _engine_context(engine_context) {}
ChunkPool(EngineContext& engine_context, vmath::u32 max_chunks) :
_chunks_count(max_chunks), _engine_context(engine_context) {}
/// @brief initializes chunk pool
/// @param max_chunks number of chunks in a pool
void init(vmath::i32 max_chunks) noexcept;
void init() noexcept;
/// @brief allocates chunk from _free_chunks
/// @param voxel_write_data function writing voxel data to voxel data region (CPU)
/// @param position position of the chunk
Expand Down
4 changes: 1 addition & 3 deletions src/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ using namespace ve001;

// #define SIMPLE_GENERATOR
// #define MAX_DIV_FACTOR 1

static constexpr u64 MAX_DIV_FACTOR{ 32UL };

// #define NO_RESIZE

Engine::Engine(Vec3f32 world_size, Vec3f32 initial_position, Vec3i32 chunk_size) : _engine_context(EngineContext{
Expand All @@ -30,6 +27,7 @@ Engine::Engine(Vec3f32 world_size, Vec3f32 initial_position, Vec3i32 chunk_size)
.chunk_max_current_mesh_size = sizeof(Vertex) * static_cast<u64>(24),
.chunk_max_current_submesh_size = sizeof(Vertex) * static_cast<u64>(24/6),
#endif
.chunk_pool_growth_coefficient = 1.5F,
.meshing_axis_progress_step = 64
}),
_world_grid(_engine_context, world_size, initial_position,
Expand Down
6 changes: 4 additions & 2 deletions src/engine/engine_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ struct EngineContext {
vmath::u64 chunk_max_possible_mesh_size;
/// @brief maximum possible mesh size of a single chunk's side after greedy meshing
vmath::u64 chunk_max_possible_submesh_size;
/// @brief maximum current mesh size of a single chunk's side's indices after greedy meshing
// vmath::u64 chunk_max_current_submesh_indices_size;
/// @brief maximum current mesh size of a single chunk after greedy meshing
vmath::u64 chunk_max_current_mesh_size;
/// @brief maximum current mesh size of a single chunk's side after greedy meshing
vmath::u64 chunk_max_current_submesh_size;
/// @brief chunk pool memory growth coefficient
vmath::f32 chunk_pool_growth_coefficient;
/// @brief max possiblenumber of visible chunks
// vmath::u32 max_visible_chunks;
/// @brief it maps to local_size_x attribute in greedy meshing compute shader
vmath::i32 meshing_axis_progress_step;
};
Expand Down
4 changes: 2 additions & 2 deletions src/engine/meshing_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ struct MeshingEngine {

const EngineContext& _engine_context;

MeshingEngine(const EngineContext& engine_context)
MeshingEngine(const EngineContext& engine_context, vmath::u32 max_chunks)
: _engine_context(engine_context),
_commands(512, Command{}) {}
_commands(max_chunks, Command{}) {}

void init(vmath::u32 vbo_id);

Expand Down
2 changes: 1 addition & 1 deletion src/engine/noise_terrain_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void NoiseTerrainGenerator::threadInit() {
// fn_add->SetRHS(fn_position_output);

_smart_node = FastNoise::NewFromEncodedNodeTree(
"IQAZABAAexQOQA0AAwAAAAAAAEAIAAAAAAA/AAAAAAABAwCPwnU9AQQAmpkZPzMz87+uR+G+9ig8QOxRWEBxPYo/AAAAAAAAAAD//wEAAClcjz4="
"IQAZABAAexQoQA0AAwAAAAAAAEAIAAAAAAA/AAAAAAABAwCPwnU9AQQAAAAAAArXo78AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wEAAClcjz4="
);//fn_add;
}
std::optional<std::span<const vmath::u16>> NoiseTerrainGenerator::gen(vmath::Vec3i32 chunk_position) {
Expand Down
4 changes: 4 additions & 0 deletions src/engine/ringbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ struct RingBuffer {
RingBuffer(std::size_t size, T fill_value)
: _buffer(size, fill_value) {}

void resize(std::size_t new_size) {
_buffer.resize(new_size);
}

bool write(T value) noexcept {
if (_writer_index == _reader_index && !_empty) {
return false;
Expand Down
116 changes: 49 additions & 67 deletions src/engine/world_grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ static bool isInElipsoid(Vec3f32 ellipsoid_center, Vec3f32 semi_axes, Vec3f32 po
(diff[0]*diff[0])/(semi_axes[0]*semi_axes[0]) +
(diff[1]*diff[1])/(semi_axes[1]*semi_axes[1]) +
(diff[2]*diff[2])/(semi_axes[2]*semi_axes[2])) <= 1.F;
// return semi_axes[0]*semi_axes[0] >
// (point[0] - ellipsoid_center[0]) * (point[0] - ellipsoid_center[0]) +
// (point[1] - ellipsoid_center[1]) * (point[1] - ellipsoid_center[1]) +
// (point[2] - ellipsoid_center[2]) * (point[2] - ellipsoid_center[2]);

// return true;
}

static bool isInBoundingBox(Vec3i32 p0, Vec3i32 p1, Vec3i32 point) {
Expand All @@ -30,14 +24,22 @@ static bool isInBoundingBox(Vec3i32 p0, Vec3i32 p1, Vec3i32 point) {
point[2] <= p1[2]);
}

static u32 computeMaxVisibleChunks(Vec3i32 chunk_size, Vec3f32 ellipsoid_semi_axes) {
const auto chunk_size_f32 = Vec3f32::cast(chunk_size);
const auto max_chunks_along_x = static_cast<i32>(std::floor((2.F * ellipsoid_semi_axes[0])/chunk_size_f32[0]));
const auto max_chunks_along_y = static_cast<i32>(std::floor((2.F * ellipsoid_semi_axes[1])/chunk_size_f32[1]));
const auto max_chunks_along_z = static_cast<i32>(std::floor((2.F * ellipsoid_semi_axes[2])/chunk_size_f32[2]));

return max_chunks_along_x * max_chunks_along_y * max_chunks_along_z;
}


WorldGrid::WorldGrid(EngineContext& engine_context, vmath::Vec3f32 world_size, vmath::Vec3f32 initial_position, std::unique_ptr<ChunkGenerator> chunk_generator) : _engine_context(engine_context),
_current_position(initial_position), _semi_axes(world_size), _chunk_pool(engine_context),
WorldGrid::WorldGrid(EngineContext& engine_context, vmath::Vec3f32 world_size, vmath::Vec3f32 initial_position, std::unique_ptr<ChunkGenerator> chunk_generator) :
_engine_context(engine_context),
_max_visible_chunks(computeMaxVisibleChunks(_engine_context.chunk_size, world_size)),
_current_position(initial_position), _semi_axes(world_size), _chunk_pool(engine_context, _max_visible_chunks),
_grid_size(Vec3i32::add(Vec3i32::mulScalar(Vec3i32::cast(Vec3f32::div(world_size, Vec3f32::cast(engine_context.chunk_size))), 2), 1)),
_chunk_data_streamer(std::move(chunk_generator), 512),
_to_allocate_chunks(512)
_chunk_data_streamer(std::move(chunk_generator), _max_visible_chunks),
_to_allocate_chunks(_max_visible_chunks)
{
}

Expand All @@ -47,26 +49,6 @@ constexpr std::array<Vec3i32, 6> NEIGHBOURS_OFFSETS{{
{0, 0, 1}, { 0, 0,-1},
}};

// #define DEBUG_WORLD_GRID

struct Timer {
f64& duration;

Timer(f64& duration) :
duration(duration), begin_timer(std::chrono::high_resolution_clock::now()) {}

~Timer() {
const auto end_timer{std::chrono::high_resolution_clock::now()};

const auto begin_ms{std::chrono::time_point_cast<std::chrono::microseconds>(begin_timer).time_since_epoch().count()};
const auto end_ms{std::chrono::time_point_cast<std::chrono::microseconds>(end_timer).time_since_epoch().count()};

duration = static_cast<f64>(end_ms - begin_ms)/1000.;
}

const std::chrono::time_point<std::chrono::high_resolution_clock> begin_timer;
};

void WorldGrid::init() {
const auto chunk_size_f32 = Vec3f32::cast(_engine_context.chunk_size);
const auto max_chunks_along_x = static_cast<i32>(std::floor((2.F * _semi_axes[0])/chunk_size_f32[0]));
Expand All @@ -77,7 +59,7 @@ void WorldGrid::init() {
_tmp_indices.resize(_grid_size[0] * _grid_size[1] * _grid_size[2], VisibleChunk::INVALID_NEIGHBOUR_INDEX);

_visible_chunks.reserve(max_chunks);
_chunk_pool.init(max_chunks);
_chunk_pool.init();
_free_visible_chunk_ids.resize(max_chunks);
u32 i{ 0U };
for (auto& visible_chunk_id : _free_visible_chunk_ids) {
Expand Down Expand Up @@ -143,44 +125,44 @@ static u32 oppositeNeighbour(u32 neighbour) {
return neighbour - (neighbour & 0x1U) + (~neighbour & 0x1U);
}

bool WorldGrid::validate() {
const auto position_in_chunk_space = Vec3i32::cast(vmath::vroundf(Vec3f32::div(_current_position, Vec3f32::cast(_engine_context.chunk_size))));
const auto half_grid_size = Vec3i32::divScalar(_grid_size, 2);//1;
const auto world_p0_in_chunk_space = Vec3i32::sub(position_in_chunk_space, half_grid_size);
const auto world_p1_in_chunk_space = Vec3i32::add(position_in_chunk_space, half_grid_size/*Vec3i32::sub(half_grid_size, {1})*/);

for (const auto& visible_chunk : _visible_chunks) {
if (isInBoundingBox(world_p0_in_chunk_space, world_p1_in_chunk_space, visible_chunk.position_in_chunks)) {
u32 nonempty_neighbours{ 0U };
for (u32 neighbour{ 0U }; neighbour < 6U; ++neighbour) {
if (visible_chunk.neighbours_indices[neighbour] != VisibleChunk::INVALID_NEIGHBOUR_INDEX) {
const auto offset = NEIGHBOURS_OFFSETS[neighbour];
const auto& visible_chunk_neighbour = _visible_chunks[visible_chunk.neighbours_indices[neighbour]];

const auto comp_offset = Vec3i32::sub(visible_chunk_neighbour.position_in_chunks, visible_chunk.position_in_chunks);
++nonempty_neighbours;
if (comp_offset[0] != offset[0] ||
comp_offset[1] != offset[1] ||
comp_offset[2] != offset[2]) {
// bool WorldGrid::validate() {
// const auto position_in_chunk_space = Vec3i32::cast(vmath::vroundf(Vec3f32::div(_current_position, Vec3f32::cast(_engine_context.chunk_size))));
// const auto half_grid_size = Vec3i32::divScalar(_grid_size, 2);//1;
// const auto world_p0_in_chunk_space = Vec3i32::sub(position_in_chunk_space, half_grid_size);
// const auto world_p1_in_chunk_space = Vec3i32::add(position_in_chunk_space, half_grid_size/*Vec3i32::sub(half_grid_size, {1})*/);

// for (const auto& visible_chunk : _visible_chunks) {
// if (isInBoundingBox(world_p0_in_chunk_space, world_p1_in_chunk_space, visible_chunk.position_in_chunks)) {
// u32 nonempty_neighbours{ 0U };
// for (u32 neighbour{ 0U }; neighbour < 6U; ++neighbour) {
// if (visible_chunk.neighbours_indices[neighbour] != VisibleChunk::INVALID_NEIGHBOUR_INDEX) {
// const auto offset = NEIGHBOURS_OFFSETS[neighbour];
// const auto& visible_chunk_neighbour = _visible_chunks[visible_chunk.neighbours_indices[neighbour]];

// const auto comp_offset = Vec3i32::sub(visible_chunk_neighbour.position_in_chunks, visible_chunk.position_in_chunks);
// ++nonempty_neighbours;
// if (comp_offset[0] != offset[0] ||
// comp_offset[1] != offset[1] ||
// comp_offset[2] != offset[2]) {

return false;
}
}
}
if (visible_chunk.neighbours_count != nonempty_neighbours) {
return false;
}
} else {
return false;
}
}

return true;
}
// return false;
// }
// }
// }
// if (visible_chunk.neighbours_count != nonempty_neighbours) {
// return false;
// }
// } else {
// return false;
// }
// }

// return true;
// }


void WorldGrid::update(Vec3f32 new_position) {
static constexpr f32 epsilon{ .01F };
static constexpr f32 epsilon{ .1F };
const auto move_vec = Vec3f32::sub(new_position, _current_position);
if (std::abs(move_vec[0]) <= epsilon &&
std::abs(move_vec[1]) <= epsilon &&
Expand All @@ -191,7 +173,7 @@ void WorldGrid::update(Vec3f32 new_position) {
_current_position = new_position;

const auto position_in_chunk_space = Vec3i32::cast(vmath::vroundf(Vec3f32::div(_current_position, Vec3f32::cast(_engine_context.chunk_size))));
const auto half_grid_size = Vec3i32::divScalar(_grid_size, 2);//1;
const auto half_grid_size = Vec3i32::divScalar(_grid_size, 2);
const auto world_p0_in_chunk_space = Vec3i32::sub(position_in_chunk_space, half_grid_size);
const auto world_p1_in_chunk_space = Vec3i32::add(position_in_chunk_space, half_grid_size);

Expand Down
Loading

0 comments on commit 23d2718

Please sign in to comment.