Skip to content

Commit

Permalink
Reduce load when there are many changes at once in the same chunk
Browse files Browse the repository at this point in the history
  • Loading branch information
xtreme8000 committed Sep 10, 2020
1 parent 5591538 commit a838b06
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 33 deletions.
76 changes: 52 additions & 24 deletions src/chunk.c
Expand Up @@ -35,9 +35,11 @@
#include "tesselator.h"
#include "chunk.h"
#include "channel.h"
#include "utils.h"

struct chunk chunks[CHUNKS_PER_DIM * CHUNKS_PER_DIM];

HashTable chunk_block_queue;
struct channel chunk_work_queue;
struct channel chunk_result_queue;

Expand All @@ -51,7 +53,7 @@ struct chunk_result_packet {
struct chunk* chunk;
int max_height;
struct tesselator tesselator;
uint32_t minimap_data[CHUNK_SIZE * CHUNK_SIZE];
uint32_t* minimap_data;
};

struct chunk_render_call {
Expand All @@ -73,6 +75,7 @@ void chunk_init() {

channel_create(&chunk_work_queue, sizeof(struct chunk_work_packet), CHUNKS_PER_DIM * CHUNKS_PER_DIM);
channel_create(&chunk_result_queue, sizeof(struct chunk_result_packet), CHUNKS_PER_DIM * CHUNKS_PER_DIM);
ht_setup(&chunk_block_queue, sizeof(struct chunk*), sizeof(struct chunk_result_packet), 64);

int chunk_enabled_cores = min(max(window_cpucores() / 2, 1), CHUNK_WORKERS_MAX);
log_info("%i cores enabled for chunk generation", chunk_enabled_cores);
Expand Down Expand Up @@ -178,6 +181,7 @@ void* chunk_generate(void* data) {

struct chunk_result_packet result;
result.chunk = work.chunk;
result.minimap_data = malloc(CHUNK_SIZE * CHUNK_SIZE * sizeof(uint32_t));
tesselator_create(&result.tesselator, VERTEX_INT, 0);

uint32_t blocks_count;
Expand Down Expand Up @@ -557,9 +561,7 @@ void chunk_generate_naive(struct libvxl_block* blocks, int count, uint32_t* soli
int y = map_size_y - 1 - key_getz(blk->position);
int z = key_gety(blk->position);

if(*max_height < y) {
*max_height = y;
}
*max_height = max(*max_height, y);

uint32_t col = blk->color;
int r = blue(col);
Expand Down Expand Up @@ -727,25 +729,38 @@ void chunk_generate_naive(struct libvxl_block* blocks, int count, uint32_t* soli
void chunk_update_all() {
size_t drain = channel_size(&chunk_result_queue);

for(size_t k = 0; k < drain; k++) {
struct chunk_result_packet result;
channel_await(&chunk_result_queue, &result);
if(drain > 0) {
struct chunk_result_packet results[drain];

if(!result.chunk->created) {
glx_displaylist_create(&result.chunk->display_list, true, false);
result.chunk->created = true;
for(size_t k = 0; k < drain; k++) {
channel_await(&chunk_result_queue, results + k);
results[k].chunk->updated = false;
}

result.chunk->last_update = window_time();
result.chunk->max_height = result.max_height;
struct chunk_result_packet* result = results + drain - 1;

for(size_t k = 0; k < drain; k++, result--) {
if(!result->chunk->updated) {
result->chunk->updated = true;

if(!result->chunk->created) {
glx_displaylist_create(&result->chunk->display_list, true, false);
result->chunk->created = true;
}

result->chunk->max_height = result->max_height;

tesselator_glx(&result->tesselator, &result->chunk->display_list);

tesselator_glx(&result.tesselator, &result.chunk->display_list);
tesselator_free(&result.tesselator);
glBindTexture(GL_TEXTURE_2D, texture_minimap.texture_id);
glTexSubImage2D(GL_TEXTURE_2D, 0, result->chunk->x * CHUNK_SIZE, result->chunk->y * CHUNK_SIZE,
CHUNK_SIZE, CHUNK_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, result->minimap_data);
glBindTexture(GL_TEXTURE_2D, 0);
}

glBindTexture(GL_TEXTURE_2D, texture_minimap.texture_id);
glTexSubImage2D(GL_TEXTURE_2D, 0, result.chunk->x * CHUNK_SIZE, result.chunk->y * CHUNK_SIZE, CHUNK_SIZE,
CHUNK_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, result.minimap_data);
glBindTexture(GL_TEXTURE_2D, 0);
tesselator_free(&result->tesselator);
free(result->minimap_data);
}
}
}

Expand All @@ -763,10 +778,23 @@ void chunk_rebuild_all() {
}

void chunk_block_update(int x, int y, int z) {
channel_put(&chunk_work_queue,
&(struct chunk_work_packet) {
.chunk = chunks + (x / CHUNK_SIZE) + (z / CHUNK_SIZE) * CHUNKS_PER_DIM,
.chunk_x = x / CHUNK_SIZE,
.chunk_y = z / CHUNK_SIZE,
});
struct chunk* c = chunks + (x / CHUNK_SIZE) + (z / CHUNK_SIZE) * CHUNKS_PER_DIM;

ht_insert(&chunk_block_queue, &c,
&(struct chunk_work_packet) {
.chunk = c,
.chunk_x = c->x,
.chunk_y = c->y,
});
}

static bool iterate_chunk_updates(void* key, void* value, void* user) {
channel_put(&chunk_work_queue, value);

return true;
}

void chunk_queue_blocks() {
ht_iterate(&chunk_block_queue, NULL, iterate_chunk_updates);
ht_clear(&chunk_block_queue);
}
3 changes: 2 additions & 1 deletion src/chunk.h
Expand Up @@ -34,7 +34,7 @@
extern struct chunk {
struct glx_displaylist display_list;
int max_height;
float last_update;
bool updated;
bool created;
int x, y;
} chunks[CHUNKS_PER_DIM * CHUNKS_PER_DIM];
Expand All @@ -51,5 +51,6 @@ void chunk_generate_naive(struct libvxl_block* blocks, int count, uint32_t* soli
int* max_height, int ao);
void chunk_rebuild_all(void);
void chunk_draw_visible(void);
void chunk_queue_blocks();

#endif
20 changes: 12 additions & 8 deletions src/map.c
Expand Up @@ -37,6 +37,7 @@
#include "minheap.h"
#include "tesselator.h"
#include "utils.h"
#include "config.h"

uint8_t* map_heights;
int map_size_x = 512;
Expand Down Expand Up @@ -518,14 +519,17 @@ void map_set(int x, int y, int z, unsigned int color) {
chunk_block_update(x + 1, y, z);
if(z < map_size_z - 1 && z_off == CHUNK_SIZE - 1)
chunk_block_update(x, y, z + 1);
if(x > 0 && z > 0 && x_off == 0 && z_off == 0)
chunk_block_update(x - 1, y, z - 1);
if(x < map_size_x - 1 && z < map_size_z - 1 && x_off == CHUNK_SIZE - 1 && z_off == CHUNK_SIZE - 1)
chunk_block_update(x + 1, y, z + 1);
if(x > 0 && z < map_size_z - 1 && x_off == 0 && z_off == CHUNK_SIZE - 1)
chunk_block_update(x - 1, y, z + 1);
if(x < map_size_x - 1 && z > 0 && x_off == CHUNK_SIZE - 1 && z_off == 0)
chunk_block_update(x + 1, y, z - 1);

if(settings.ambient_occlusion) {
if(x > 0 && z > 0 && x_off == 0 && z_off == 0)
chunk_block_update(x - 1, y, z - 1);
if(x < map_size_x - 1 && z < map_size_z - 1 && x_off == CHUNK_SIZE - 1 && z_off == CHUNK_SIZE - 1)
chunk_block_update(x + 1, y, z + 1);
if(x > 0 && z < map_size_z - 1 && x_off == 0 && z_off == CHUNK_SIZE - 1)
chunk_block_update(x - 1, y, z + 1);
if(x < map_size_x - 1 && z > 0 && x_off == CHUNK_SIZE - 1 && z_off == 0)
chunk_block_update(x + 1, y, z - 1);
}

if(x == 0)
chunk_block_update(map_size_x - 1, y, z);
Expand Down
3 changes: 3 additions & 0 deletions src/network.c
Expand Up @@ -1090,6 +1090,9 @@ int network_update() {
}
}
}

chunk_queue_blocks();

return 1;
}

Expand Down
9 changes: 9 additions & 0 deletions src/utils.c
Expand Up @@ -64,3 +64,12 @@ size_t int_hash(void* raw_key, size_t key_size) {
x = (x >> 16) ^ x;
return x;
}

void ht_iterate(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user)) {
for(size_t chain = 0; chain < ht->capacity; chain++) {
HTNode* node = ht->nodes[chain];

while(node && callback(node->key, node->value, user))
node = node->next;
}
}
3 changes: 3 additions & 0 deletions src/utils.h
Expand Up @@ -22,9 +22,12 @@

#include <stdint.h>

#include "hashtable.h"

int base64_decode(char* data, int len);

int int_cmp(void* first_key, void* second_key, size_t key_size);
size_t int_hash(void* raw_key, size_t key_size);
void ht_iterate(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user));

#endif

0 comments on commit a838b06

Please sign in to comment.