Przeglądaj źródła

more optimization

opengl-renderer-broken
Martin Dørum 4 lat temu
rodzic
commit
24b8fdcd8d

+ 2
- 2
CMakeLists.txt Wyświetl plik

add_compile_options(-g -Og) add_compile_options(-g -Og)
elseif(CMAKE_BUILD_TYPE STREQUAL DebugRelease) elseif(CMAKE_BUILD_TYPE STREQUAL DebugRelease)
message(STATUS "Build mode: DebugRelease") message(STATUS "Build mode: DebugRelease")
add_compile_options(-g -O3)
add_compile_options(-O3 -flto -DNDEBUG -g)
elseif(CMAKE_BUILD_TYPE STREQUAL Release) elseif(CMAKE_BUILD_TYPE STREQUAL Release)
message(STATUS "Build mode: 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") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
else() else()
message(FATAL_ERROR "CMAKE_BUILD_TYPE must be Debug or Release.") message(FATAL_ERROR "CMAKE_BUILD_TYPE must be Debug or Release.")

+ 19
- 4
libswan/include/swan/Chunk.h Wyświetl plik

data_.reset(new uint8_t[CHUNK_WIDTH * CHUNK_HEIGHT * sizeof(Tile::ID)]); 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 render(const Context &ctx, SDL_Renderer *rnd);


void compress(); void compress();

+ 1
- 1
libswan/include/swan/World.h Wyświetl plik

WorldPlane &addPlane(const std::string &gen); WorldPlane &addPlane(const std::string &gen);
WorldPlane &addPlane() { return addPlane(default_world_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::ID getTileID(const std::string &name);
Tile &getTile(const std::string &name); Tile &getTile(const std::string &name);
Item &getItem(const std::string &name); Item &getItem(const std::string &name);

+ 3
- 0
libswan/include/swan/WorldPlane.h Wyświetl plik



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

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


private: private:
std::map<std::pair<int, int>, Chunk> chunks_; std::map<std::pair<int, int>, Chunk> chunks_;
std::vector<Chunk *> active_chunks_; std::vector<Chunk *> active_chunks_;
std::vector<std::pair<ChunkPos, Chunk *>> tick_chunks_;
std::vector<std::unique_ptr<Entity>> entities_; std::vector<std::unique_ptr<Entity>> entities_;


std::deque<Chunk *> chunk_init_list_; std::deque<Chunk *> chunk_init_list_;

+ 0
- 19
libswan/src/Chunk.cc Wyświetl plik



uint8_t *Chunk::renderbuf = new uint8_t[CHUNK_WIDTH * TILE_SIZE * CHUNK_HEIGHT * TILE_SIZE * 4]; 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() { void Chunk::compress() {
if (isCompressed()) if (isCompressed())
return; return;

+ 1
- 5
libswan/src/World.cc Wyświetl plik



static void chunkLine(int l, WorldPlane &plane, ChunkPos &abspos, const Vec2i &dir) { static void chunkLine(int l, WorldPlane &plane, ChunkPos &abspos, const Vec2i &dir) {
for (int i = 0; i < l; ++i) { for (int i = 0; i < l; ++i) {
plane.getChunk(abspos);
plane.slowGetChunk(abspos).keepActive();
abspos += dir; abspos += dir;
} }
} }
return iter->second; return iter->second;
} }


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

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

+ 17
- 31
libswan/src/WorldPlane.cc Wyświetl plik



// This function will be a bit weird because it's a really fucking hot function. // This function will be a bit weird because it's a really fucking hot function.
Chunk &WorldPlane::getChunk(ChunkPos pos) { 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; 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); auto iter = chunks_.find(pos);


// Create chunk if that turns out to be necessary // Create chunk if that turns out to be necessary
active_chunks_.push_back(&chunk); active_chunks_.push_back(&chunk);
chunk_init_list_.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(); iter->second.keepActive();
active_chunks_.push_back(&iter->second); active_chunks_.push_back(&iter->second);
chunk_init_list_.push_back(&iter->second); chunk_init_list_.push_back(&iter->second);
} }


Tile::ID WorldPlane::getTileID(TilePos pos) { 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) { Tile &WorldPlane::getTile(TilePos pos) {
} }


void WorldPlane::tick(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_) for (auto &ent: entities_)
ent->tick(getContext(), dt); ent->tick(getContext(), dt);



Ładowanie…
Anuluj
Zapisz