BufferPool
This commit is contained in:
parent
a7a447552e
commit
4e5f6a5a7d
@ -1,27 +1,25 @@
|
||||
#include "WorldFiles.h"
|
||||
|
||||
#include "rle.h"
|
||||
#include "../window/Camera.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../physics/Hitbox.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../typedefs.h"
|
||||
#include "../maths/voxmaths.h"
|
||||
#include "../world/World.h"
|
||||
#include "../lighting/Lightmap.h"
|
||||
|
||||
#include "../coders/byte_utils.h"
|
||||
#include "../util/data_io.h"
|
||||
#include "../coders/json.h"
|
||||
#include "../constants.h"
|
||||
#include "../items/ItemDef.h"
|
||||
#include "../items/Inventory.h"
|
||||
|
||||
#include "../data/dynamic.h"
|
||||
#include "../content/Content.h"
|
||||
#include "../core_defs.h"
|
||||
#include "../data/dynamic.h"
|
||||
#include "../items/Inventory.h"
|
||||
#include "../items/ItemDef.h"
|
||||
#include "../lighting/Lightmap.h"
|
||||
#include "../maths/voxmaths.h"
|
||||
#include "../objects/Player.h"
|
||||
#include "../physics/Hitbox.h"
|
||||
#include "../typedefs.h"
|
||||
#include "../util/data_io.h"
|
||||
#include "../voxels/Block.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../voxels/voxel.h"
|
||||
#include "../window/Camera.h"
|
||||
#include "../world/World.h"
|
||||
#include "rle.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
@ -48,7 +46,8 @@ regfile::regfile(fs::path filename) : file(filename) {
|
||||
version = header[8];
|
||||
if (uint(version) > REGION_FORMAT_VERSION) {
|
||||
throw illegal_region_format(
|
||||
"region format "+std::to_string(version)+" is not supported");
|
||||
"region format "+std::to_string(version)+" is not supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,13 +94,7 @@ uint WorldRegion::getChunkDataSize(uint x, uint z) {
|
||||
return sizes[z * REGION_SIZE + x];
|
||||
}
|
||||
|
||||
WorldFiles::WorldFiles(fs::path directory, const DebugSettings& settings)
|
||||
: directory(directory),
|
||||
generatorTestMode(settings.generatorTestMode),
|
||||
doWriteLights(settings.doWriteLights)
|
||||
{
|
||||
compressionBuffer = std::make_unique<ubyte[]>(CHUNK_DATA_LEN * 2);
|
||||
// just ignore this
|
||||
WorldFiles::WorldFiles(fs::path directory) : directory(directory) {
|
||||
for (uint i = 0; i < sizeof(layers)/sizeof(RegionsLayer); i++) {
|
||||
layers[i].layer = i;
|
||||
}
|
||||
@ -110,6 +103,13 @@ WorldFiles::WorldFiles(fs::path directory, const DebugSettings& settings)
|
||||
layers[REGION_LAYER_INVENTORIES].folder = directory/fs::path("inventories");
|
||||
}
|
||||
|
||||
WorldFiles::WorldFiles(fs::path directory, const DebugSettings& settings)
|
||||
: WorldFiles(directory)
|
||||
{
|
||||
generatorTestMode = settings.generatorTestMode;
|
||||
doWriteLights = settings.doWriteLights;
|
||||
}
|
||||
|
||||
WorldFiles::~WorldFiles() {
|
||||
}
|
||||
|
||||
@ -139,12 +139,13 @@ WorldRegion* WorldFiles::getOrCreateRegion(int x, int z, int layer) {
|
||||
}
|
||||
|
||||
std::unique_ptr<ubyte[]> WorldFiles::compress(const ubyte* src, size_t srclen, size_t& len) {
|
||||
ubyte* buffer = this->compressionBuffer.get();
|
||||
auto buffer = bufferPool.get();
|
||||
ubyte* bytes = buffer.get();
|
||||
|
||||
len = extrle::encode(src, srclen, buffer);
|
||||
len = extrle::encode(src, srclen, bytes);
|
||||
auto data = std::make_unique<ubyte[]>(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
data[i] = buffer[i];
|
||||
data[i] = bytes[i];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@ -164,10 +165,6 @@ inline void calc_reg_coords(
|
||||
localZ = z - (regionZ * REGION_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/// @brief Store chunk voxels data in region
|
||||
/// @param x chunk.x
|
||||
/// @param z chunk.z
|
||||
void WorldFiles::put(int x, int z, int layer, std::unique_ptr<ubyte[]> data, size_t size, bool rle) {
|
||||
if (rle) {
|
||||
size_t compressedSize;
|
||||
@ -318,7 +315,7 @@ ubyte* WorldFiles::getData(
|
||||
if (data == nullptr) {
|
||||
auto regfile = getRegFile(glm::ivec3(regionX, regionZ, layer));
|
||||
if (regfile != nullptr) {
|
||||
data = readChunkData(x, z, size, regfile.get());
|
||||
data = readChunkData(x, z, size, regfile.get()).release();
|
||||
}
|
||||
if (data != nullptr) {
|
||||
region->put(localX, localZ, data, size);
|
||||
@ -391,7 +388,7 @@ std::shared_ptr<regfile> WorldFiles::createRegFile(glm::ivec3 coord) {
|
||||
}
|
||||
}
|
||||
|
||||
ubyte* WorldFiles::readChunkData(
|
||||
std::unique_ptr<ubyte[]> WorldFiles::readChunkData(
|
||||
int x,
|
||||
int z,
|
||||
uint32_t& length,
|
||||
@ -405,7 +402,6 @@ ubyte* WorldFiles::readChunkData(
|
||||
int chunkIndex = localZ * REGION_SIZE + localX;
|
||||
|
||||
files::rafile& file = rfile->file;
|
||||
|
||||
size_t file_size = file.length();
|
||||
size_t table_offset = file_size - REGION_CHUNKS_COUNT * 4;
|
||||
|
||||
@ -420,8 +416,8 @@ ubyte* WorldFiles::readChunkData(
|
||||
file.seekg(offset);
|
||||
file.read((char*)(&offset), 4);
|
||||
length = dataio::read_int32_big((const ubyte*)(&offset), 0);
|
||||
ubyte* data = new ubyte[length]{};
|
||||
file.read((char*)data, length);
|
||||
auto data = std::make_unique<ubyte[]>(length);
|
||||
file.read((char*)data.get(), length);
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -434,16 +430,11 @@ void WorldFiles::fetchChunks(WorldRegion* region, int x, int z, regfile* file) {
|
||||
int chunk_x = (i % REGION_SIZE) + x * REGION_SIZE;
|
||||
int chunk_z = (i / REGION_SIZE) + z * REGION_SIZE;
|
||||
if (chunks[i] == nullptr) {
|
||||
chunks[i] = readChunkData(chunk_x, chunk_z, sizes[i], file);
|
||||
chunks[i] = readChunkData(chunk_x, chunk_z, sizes[i], file).release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Write or rewrite region file
|
||||
/// @param x region X
|
||||
/// @param z region Z
|
||||
/// @param layer used as third part of openRegFiles map key
|
||||
/// (see REGION_LAYER_* constants)
|
||||
void WorldFiles::writeRegion(int x, int z, int layer, WorldRegion* entry){
|
||||
fs::path filename = layers[layer].folder/getRegionFilename(x, z);
|
||||
|
||||
@ -616,3 +607,11 @@ void WorldFiles::processRegionVoxels(int x, int z, regionproc func) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs::path WorldFiles::getFolder() const {
|
||||
return directory;
|
||||
}
|
||||
|
||||
fs::path WorldFiles::getRegionsFolder(int layer) const {
|
||||
return layers[layer].folder;
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "../settings.h"
|
||||
#include "../content/ContentPack.h"
|
||||
#include "../voxels/Chunk.h"
|
||||
#include "../util/BufferPool.h"
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
@ -84,13 +85,17 @@ struct RegionsLayer {
|
||||
};
|
||||
|
||||
class WorldFiles {
|
||||
fs::path directory;
|
||||
std::unordered_map<glm::ivec3, std::unique_ptr<regfile>> openRegFiles;
|
||||
std::mutex regFilesMutex;
|
||||
std::condition_variable regFilesCv;
|
||||
|
||||
RegionsLayer layers[3] {};
|
||||
bool generatorTestMode = false;
|
||||
bool doWriteLights = true;
|
||||
util::BufferPool<ubyte> bufferPool {
|
||||
std::max(CHUNK_DATA_LEN, LIGHTMAP_DATA_LEN) * 2
|
||||
};
|
||||
|
||||
void writeWorldInfo(const World* world);
|
||||
fs::path getRegionFilename(int x, int y) const;
|
||||
fs::path getWorldFile() const;
|
||||
fs::path getIndicesFile() const;
|
||||
@ -112,12 +117,13 @@ class WorldFiles {
|
||||
/// @param dstlen max expected length of source buffer
|
||||
/// @return decompressed bytes array
|
||||
std::unique_ptr<ubyte[]> decompress(const ubyte* src, size_t srclen, size_t dstlen);
|
||||
|
||||
ubyte* readChunkData(int x, int y, uint32_t& length, regfile* file);
|
||||
std::unique_ptr<ubyte[]> readChunkData(int x, int y, uint32_t& length, regfile* file);
|
||||
|
||||
void fetchChunks(WorldRegion* region, int x, int y, regfile* file);
|
||||
|
||||
void writeWorldInfo(const World* world);
|
||||
void writeRegions(int layer);
|
||||
void writeIndices(const ContentIndices* indices);
|
||||
|
||||
ubyte* getData(int x, int z, int layer, uint32_t& size);
|
||||
|
||||
@ -126,20 +132,23 @@ class WorldFiles {
|
||||
std::shared_ptr<regfile> useRegFile(glm::ivec3 coord);
|
||||
std::shared_ptr<regfile> createRegFile(glm::ivec3 coord);
|
||||
public:
|
||||
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
||||
fs::path getPlayerFile() const;
|
||||
|
||||
fs::path directory;
|
||||
std::unique_ptr<ubyte[]> compressionBuffer;
|
||||
bool generatorTestMode;
|
||||
bool doWriteLights;
|
||||
|
||||
WorldFiles(fs::path directory);
|
||||
WorldFiles(fs::path directory, const DebugSettings& settings);
|
||||
~WorldFiles();
|
||||
|
||||
fs::path getPlayerFile() const;
|
||||
void createDirectories();
|
||||
|
||||
/// @brief Put all chunk data to regions
|
||||
void put(Chunk* chunk);
|
||||
|
||||
/// @brief Store data in specified region
|
||||
/// @param x chunk.x
|
||||
/// @param z chunk.z
|
||||
/// @param layer regions layer
|
||||
/// @param data target data
|
||||
/// @param size data size
|
||||
/// @param rle compress with ext-RLE
|
||||
void put(int x, int z, int layer, std::unique_ptr<ubyte[]> data, size_t size, bool rle);
|
||||
|
||||
std::unique_ptr<ubyte[]> getChunk(int x, int z);
|
||||
@ -148,6 +157,10 @@ public:
|
||||
|
||||
bool readWorldInfo(World* world);
|
||||
|
||||
/// @brief Write or rewrite region file
|
||||
/// @param x region X
|
||||
/// @param z region Z
|
||||
/// @param layer regions layer
|
||||
void writeRegion(int x, int y, int layer, WorldRegion* entry);
|
||||
|
||||
/// @brief Write all unsaved data to world files
|
||||
@ -156,17 +169,17 @@ public:
|
||||
void write(const World* world, const Content* content);
|
||||
|
||||
void writePacks(const std::vector<ContentPack>& packs);
|
||||
void writeIndices(const ContentIndices* indices);
|
||||
|
||||
void removeIndices(const std::vector<std::string>& packs);
|
||||
|
||||
void processRegionVoxels(int x, int z, regionproc func);
|
||||
|
||||
static const inline std::string WORLD_FILE = "world.json";
|
||||
/// @return world folder
|
||||
fs::path getFolder() const;
|
||||
fs::path getRegionsFolder(int layer) const;
|
||||
|
||||
fs::path getRegionsFolder(int layer) {
|
||||
return layers[layer].folder;
|
||||
}
|
||||
static const inline std::string WORLD_FILE = "world.json";
|
||||
static bool parseRegionFilename(const std::string& name, int& x, int& y);
|
||||
};
|
||||
|
||||
#endif /* FILES_WORLDFILES_H_ */
|
||||
|
||||
@ -112,7 +112,7 @@ std::shared_ptr<Panel> menus::create_packs_panel(
|
||||
}
|
||||
|
||||
static void reopen_world(Engine* engine, World* world) {
|
||||
std::string wname = world->wfile->directory.stem().u8string();
|
||||
std::string wname = world->wfile->getFolder().stem().u8string();
|
||||
engine->setScreen(nullptr);
|
||||
engine->setScreen(std::make_shared<MenuScreen>(engine));
|
||||
menus::open_world(wname, engine, true);
|
||||
@ -140,7 +140,7 @@ void menus::remove_packs(
|
||||
|
||||
runnable removeFunc = [=]() {
|
||||
controller->saveWorld();
|
||||
auto manager = engine->createPacksManager(world->wfile->directory);
|
||||
auto manager = engine->createPacksManager(world->wfile->getFolder());
|
||||
manager.scan();
|
||||
|
||||
auto names = PacksManager::getNames(world->getPacks());
|
||||
@ -199,7 +199,7 @@ void create_content_panel(Engine* engine, LevelController* controller) {
|
||||
auto new_packs = PacksManager::getNames(world->getPacks());
|
||||
new_packs.push_back(pack.id);
|
||||
|
||||
auto manager = engine->createPacksManager(world->wfile->directory);
|
||||
auto manager = engine->createPacksManager(world->wfile->getFolder());
|
||||
manager.scan();
|
||||
try {
|
||||
new_packs = manager.assembly(new_packs);
|
||||
|
||||
37
src/util/BufferPool.h
Normal file
37
src/util/BufferPool.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef UTIL_BUFFER_POOL_H_
|
||||
#define UTIL_BUFFER_POOL_H_
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace util {
|
||||
template<class T>
|
||||
class BufferPool {
|
||||
std::vector<std::unique_ptr<T[]>> buffers;
|
||||
std::queue<T*> freeBuffers;
|
||||
std::mutex mutex;
|
||||
size_t bufferSize;
|
||||
public:
|
||||
BufferPool(size_t bufferSize) : bufferSize(bufferSize) {
|
||||
}
|
||||
|
||||
std::shared_ptr<T[]> get() {
|
||||
std::lock_guard lock(mutex);
|
||||
if (freeBuffers.empty()) {
|
||||
buffers.emplace_back(std::make_unique<T[]>(bufferSize));
|
||||
freeBuffers.push(buffers[buffers.size()-1].get());
|
||||
}
|
||||
auto* buffer = freeBuffers.front();
|
||||
freeBuffers.pop();
|
||||
return std::shared_ptr<T[]>(buffer, [this](T* ptr) {
|
||||
freeBuffers.push(ptr);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // UTIL_BUFFER_POOL_H_
|
||||
Loading…
x
Reference in New Issue
Block a user