Browse Source

more optimization

opengl-renderer-broken
Martin Dørum 4 years ago
parent
commit
24b8fdcd8d

+ 2
- 2
CMakeLists.txt View File

@@ -31,10 +31,10 @@ elseif(CMAKE_BUILD_TYPE STREQUAL Debug)
add_compile_options(-g -Og)
elseif(CMAKE_BUILD_TYPE STREQUAL DebugRelease)
message(STATUS "Build mode: DebugRelease")
add_compile_options(-g -O3)
add_compile_options(-O3 -flto -DNDEBUG -g)
elseif(CMAKE_BUILD_TYPE STREQUAL Release)
message(STATUS "Build mode: Release")
add_compile_options(-O3 -flto)
add_compile_options(-O3 -flto -DNDEBUG)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
else()
message(FATAL_ERROR "CMAKE_BUILD_TYPE must be Debug or Release.")

+ 19
- 4
libswan/include/swan/Chunk.h View File

@@ -28,10 +28,25 @@ public:
data_.reset(new uint8_t[CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID)]);
}

Tile::ID *getTileData();
Tile::ID getTileID(RelPos pos);
void setTileID(RelPos pos, Tile::ID id, SDL_Texture *tex);
void setTileData(RelPos pos, Tile::ID id);
Tile::ID *getTileData() {
assert(isActive());
return (Tile::ID *)data_.get();
}

Tile::ID getTileID(RelPos pos) {
return getTileData()[pos.y * CHUNK_WIDTH + pos.x];
}

void setTileID(RelPos pos, Tile::ID id, SDL_Texture *tex) {
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
draw_list_.push_back({ pos, tex });
}

void setTileData(RelPos pos, Tile::ID id) {
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
need_render_ = true;
}

void render(const Context &ctx, SDL_Renderer *rnd);

void compress();

+ 1
- 1
libswan/include/swan/World.h View File

@@ -31,7 +31,7 @@ public:
WorldPlane &addPlane(const std::string &gen);
WorldPlane &addPlane() { return addPlane(default_world_gen_); }

Tile &getTileByID(Tile::ID id);
Tile &getTileByID(Tile::ID id) { return *tiles_[id]; }
Tile::ID getTileID(const std::string &name);
Tile &getTile(const std::string &name);
Item &getItem(const std::string &name);

+ 3
- 0
libswan/include/swan/WorldPlane.h View File

@@ -35,8 +35,10 @@ public:

bool hasChunk(ChunkPos pos);
Chunk &getChunk(ChunkPos pos);
Chunk &slowGetChunk(ChunkPos pos);
void setTileID(TilePos pos, Tile::ID id);
void setTile(TilePos pos, const std::string &name);

Tile::ID getTileID(TilePos pos);
Tile &getTile(TilePos pos);

@@ -68,6 +70,7 @@ public:
private:
std::map<std::pair<int, int>, Chunk> chunks_;
std::vector<Chunk *> active_chunks_;
std::vector<std::pair<ChunkPos, Chunk *>> tick_chunks_;
std::vector<std::unique_ptr<Entity>> entities_;

std::deque<Chunk *> chunk_init_list_;

+ 0
- 19
libswan/src/Chunk.cc View File

@@ -15,25 +15,6 @@ namespace Swan {

uint8_t *Chunk::renderbuf = new uint8_t[CHUNK_WIDTH * TILE_SIZE * CHUNK_HEIGHT * TILE_SIZE * 4];

Tile::ID *Chunk::getTileData() {
assert(isActive());
return (Tile::ID *)data_.get();
}

Tile::ID Chunk::getTileID(RelPos pos) {
return getTileData()[pos.y * CHUNK_WIDTH + pos.x];
}

void Chunk::setTileID(RelPos pos, Tile::ID id, SDL_Texture *tex) {
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
draw_list_.push_back({ pos, tex });
}

void Chunk::setTileData(RelPos pos, Tile::ID id) {
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
need_render_ = true;
}

void Chunk::compress() {
if (isCompressed())
return;

+ 1
- 5
libswan/src/World.cc View File

@@ -11,7 +11,7 @@ namespace Swan {

static void chunkLine(int l, WorldPlane &plane, ChunkPos &abspos, const Vec2i &dir) {
for (int i = 0; i < l; ++i) {
plane.getChunk(abspos);
plane.slowGetChunk(abspos).keepActive();
abspos += dir;
}
}
@@ -122,10 +122,6 @@ Tile::ID World::getTileID(const std::string &name) {
return iter->second;
}

Tile &World::getTileByID(Tile::ID id) {
return *tiles_[id];
}

Tile &World::getTile(const std::string &name) {
Tile::ID id = getTileID(name);
return getTileByID(id);

+ 17
- 31
libswan/src/WorldPlane.cc View File

@@ -71,35 +71,18 @@ bool WorldPlane::hasChunk(ChunkPos pos) {

// This function will be a bit weird because it's a really fucking hot function.
Chunk &WorldPlane::getChunk(ChunkPos pos) {

// This branch should be really predictable, there should basically never
// be no active chunks
if (active_chunks_.size() != 0) {

// The last chunk should be the most actively used chunk
Chunk *chunk = active_chunks_.back();
if (chunk->pos_ == pos) {
chunk->keepActive();
// First, look through all chunks which have been in use this tick
for (auto [chpos, chunk]: tick_chunks_) {
if (chpos == pos)
return *chunk;
}

// Linear search through a small array is probably faster than tree lookup.
// Loop backwards because the hottest chunks should be at the end.
for (ssize_t i = active_chunks_.size() - 2; i >= 0; --i) {
chunk = active_chunks_[i];
if (chunk->pos_ == pos) {
chunk->keepActive();

// Ensure that the hot chunk is at the end by bubbling this one up
active_chunks_[i] = active_chunks_[i + 1];
active_chunks_[i + 1] = chunk;
return *chunk;
}
}
}

// Slow path: Find a chunk in our global chunk map,
// creating a new one if necessary
Chunk &chunk = slowGetChunk(pos);
tick_chunks_.push_back({ pos, &chunk });
return chunk;
}

Chunk &WorldPlane::slowGetChunk(ChunkPos pos) {
auto iter = chunks_.find(pos);

// Create chunk if that turns out to be necessary
@@ -111,8 +94,8 @@ Chunk &WorldPlane::getChunk(ChunkPos pos) {
active_chunks_.push_back(&chunk);
chunk_init_list_.push_back(&chunk);

// Otherwise, tell it that it should keep itself alive a bit longer
} else {
// Otherwise, it might not be active, so let's activate it
} else if (!iter->second.isActive()) {
iter->second.keepActive();
active_chunks_.push_back(&iter->second);
chunk_init_list_.push_back(&iter->second);
@@ -137,9 +120,7 @@ void WorldPlane::setTile(TilePos pos, const std::string &name) {
}

Tile::ID WorldPlane::getTileID(TilePos pos) {
Chunk &chunk = getChunk(chunkPos(pos));

return chunk.getTileID(relPos(pos));
return getChunk(chunkPos(pos)).getTileID(relPos(pos));
}

Tile &WorldPlane::getTile(TilePos pos) {
@@ -255,6 +236,11 @@ void WorldPlane::update(float dt) {
}

void WorldPlane::tick(float dt) {
// Any chunk which has been in use since last tick should be kept alive
for (std::pair<ChunkPos, Chunk *> &ch: tick_chunks_)
ch.second->keepActive();
tick_chunks_.clear();

for (auto &ent: entities_)
ent->tick(getContext(), dt);


Loading…
Cancel
Save