Converted both of the BiThreadQueue implementations to BiThreadPools in world.
This commit is contained in:
parent
6da513a52c
commit
caeda8c680
@ -22,4 +22,4 @@ zeus.register_block('default:dirt', {
|
|||||||
zeus.register_block('default:stone', {
|
zeus.register_block('default:stone', {
|
||||||
name = "Stone",
|
name = "Stone",
|
||||||
textures = {"default_stone"}
|
textures = {"default_stone"}
|
||||||
})
|
})
|
@ -5,7 +5,6 @@
|
|||||||
#ifndef ZEUS_LREGISTERBLOCK_H
|
#ifndef ZEUS_LREGISTERBLOCK_H
|
||||||
#define ZEUS_LREGISTERBLOCK_H
|
#define ZEUS_LREGISTERBLOCK_H
|
||||||
|
|
||||||
|
|
||||||
#include "../world/GameInstance.h"
|
#include "../world/GameInstance.h"
|
||||||
|
|
||||||
class LRegisterBlock {
|
class LRegisterBlock {
|
||||||
|
@ -8,14 +8,18 @@
|
|||||||
|
|
||||||
BlockChunk::BlockChunk(std::vector<int>* blocks) {
|
BlockChunk::BlockChunk(std::vector<int>* blocks) {
|
||||||
this->blocks = blocks;
|
this->blocks = blocks;
|
||||||
this->empty = true;
|
// this->empty = true;
|
||||||
|
//
|
||||||
for (int i : *blocks) {
|
for (int i : *blocks) {
|
||||||
if (i != 0) {
|
// std::cout << i << std::endl;
|
||||||
empty = false;
|
// if (i != 0) {
|
||||||
break;
|
// empty = false;
|
||||||
}
|
// break;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BlockChunk::getBlock(glm::vec3* pos) {
|
int BlockChunk::getBlock(glm::vec3* pos) {
|
||||||
|
@ -26,14 +26,16 @@ void GameInstance::initialize(Renderer* renderer) {
|
|||||||
//The world requires the blockAtlas for meshing and handling inputs.
|
//The world requires the blockAtlas for meshing and handling inputs.
|
||||||
world = new World(blockAtlas);
|
world = new World(blockAtlas);
|
||||||
|
|
||||||
// int SIZE = 8;
|
// world->genNewChunk(glm::vec3(0,0,0));
|
||||||
// for (int i = -SIZE; i < SIZE; i++) {
|
|
||||||
// for (int j = -4; j < 4; j++) {
|
int SIZE = 16;
|
||||||
// for (int k = -SIZE; k < SIZE; k++) {
|
for (int i = -SIZE; i < SIZE; i++) {
|
||||||
// world->genChunk(glm::vec3(i, j, k));
|
for (int j = -4; j < 4; j++) {
|
||||||
// }
|
for (int k = -SIZE; k < SIZE; k++) {
|
||||||
// }
|
world->genNewChunk(glm::vec3(i, j, k));
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInstance::update(GLfloat deltaTime) {
|
void GameInstance::update(GLfloat deltaTime) {
|
||||||
@ -50,15 +52,15 @@ void GameInstance::update(GLfloat deltaTime) {
|
|||||||
chunk.y = round(chunk.y / 16);
|
chunk.y = round(chunk.y / 16);
|
||||||
chunk.z = round(chunk.z / 16);
|
chunk.z = round(chunk.z / 16);
|
||||||
|
|
||||||
int SIZE = 16;
|
// int SIZE = 16;
|
||||||
for (int i = -SIZE; i < SIZE; i++) {
|
// for (int i = -SIZE; i < SIZE; i++) {
|
||||||
for (int j = -4; j < 4; j++) {
|
// for (int j = -4; j < 4; j++) {
|
||||||
for (int k = -SIZE; k < SIZE; k++) {
|
// for (int k = -SIZE; k < SIZE; k++) {
|
||||||
glm::vec3 adjustedPos(i + chunk.x, j + chunk.y, k + chunk.z);
|
// glm::vec3 adjustedPos(i + chunk.x, j + chunk.y, k + chunk.z);
|
||||||
world->genChunk(adjustedPos);
|
// world->genNewChunk(adjustedPos);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameInstance::draw() {
|
void GameInstance::draw() {
|
||||||
|
@ -2,133 +2,38 @@
|
|||||||
// Created by aurailus on 14/12/18.
|
// Created by aurailus on 14/12/18.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-noreturn"
|
||||||
|
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "../engine/PerlinNoise.h"
|
#include "../engine/PerlinNoise.h"
|
||||||
#include "../engine/helpers/ArrayTrans3D.h"
|
#include "../engine/helpers/ArrayTrans3D.h"
|
||||||
|
|
||||||
World::World() {
|
|
||||||
blockAtlas = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
World::World(BlockAtlas *atlas) {
|
World::World(BlockAtlas *atlas) {
|
||||||
blockAtlas = atlas;
|
blockAtlas = atlas;
|
||||||
|
|
||||||
|
for (int i = 0; i < CHUNK_THREADS; i++) {
|
||||||
|
chunkThreads.push_back(new ChunkThreadDef());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MESH_THREADS; i++) {
|
||||||
|
meshThreads.push_back(new MeshThreadDef());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::genChunk(glm::vec3 pos) {
|
void World::genNewChunk(glm::vec3 pos) {
|
||||||
if (!blockChunks.count(pos)) {
|
if (!blockChunks.count(pos)) {
|
||||||
chunkGenQueue.insert(pos);
|
chunkGenQueue.insert(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::newChunk(glm::vec3 pos, BlockChunk *c) {
|
void World::commitChunk(glm::vec3 pos, BlockChunk *c) {
|
||||||
blockChunks.insert(std::pair<glm::vec3, BlockChunk*>(pos, c));
|
blockChunks.insert(std::pair<glm::vec3, BlockChunk*>(pos, c));
|
||||||
if (!c->isEmpty()) {
|
if (!c->isEmpty()) {
|
||||||
meshGenQueue.insert(pos);
|
meshGenQueue.insert(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void chunkGenThread(World::ChunkThreadData *t) {
|
|
||||||
PerlinNoise p(0);
|
|
||||||
PerlinNoise p2(10);
|
|
||||||
|
|
||||||
auto* blocks = new std::vector<int>();
|
|
||||||
blocks->reserve(4096);
|
|
||||||
|
|
||||||
glm::vec3 innerPos, pos;
|
|
||||||
|
|
||||||
for (int ind = 0; ind < 4096; ind++) {
|
|
||||||
ArrayTrans3D::indAssignVec(ind, &innerPos);
|
|
||||||
|
|
||||||
pos.x = innerPos.x + t->pos.x * CHUNK_SIZE;
|
|
||||||
pos.y = innerPos.y + t->pos.y * CHUNK_SIZE;
|
|
||||||
pos.z = innerPos.z + t->pos.z * CHUNK_SIZE;
|
|
||||||
|
|
||||||
double val = p.noise(pos.x / (double) 32, pos.z / (double) 32, 0) * 16;
|
|
||||||
val *= p2.noise((pos.x + 16) / (double) 48, (pos.z + 16) / (double) 48, 0) * 8;
|
|
||||||
val /= 16;
|
|
||||||
val *= pow(p.noise(pos.x / (double) 64, pos.z / (double) 64, 0), 2) * 40 + 1;
|
|
||||||
val -= pos.y;
|
|
||||||
|
|
||||||
int block = (val > 0) ? (val > 1 ) ? (val > 4) ? 3 : 2 : 1 : 0;
|
|
||||||
blocks->push_back(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
t->chunk = new BlockChunk(blocks);
|
|
||||||
t->done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void meshGenThread(World::MeshThreadData *t) {
|
|
||||||
MeshGenerator().build(t->chunk, t->atlas, *(t->vertices), *(t->indices));
|
|
||||||
t->done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::handleChunkGenQueue() {
|
|
||||||
//Finalize finished threads by added the BlockChunks to the world via newChunk().
|
|
||||||
for (auto iter = chunkGenThreads.begin(); iter != chunkGenThreads.end(); ) {
|
|
||||||
ChunkThreadData* threadData = (*iter);
|
|
||||||
|
|
||||||
if (threadData->done) {
|
|
||||||
newChunk(threadData->pos, threadData->chunk);
|
|
||||||
delete threadData;
|
|
||||||
iter = chunkGenThreads.erase(iter);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create new chunk gen threads if there are chunks to be generated.
|
|
||||||
while (!chunkGenQueue.empty() && chunkGenThreads.size() < MAX_CHUNK_GEN_THREADS) {
|
|
||||||
auto it = chunkGenQueue.begin();
|
|
||||||
chunkGenQueue.erase(chunkGenQueue.begin());
|
|
||||||
glm::vec3 pos = (*it);
|
|
||||||
|
|
||||||
auto t = new ChunkThreadData(pos, blockAtlas);
|
|
||||||
auto thread = new std::thread(chunkGenThread, t);
|
|
||||||
thread->detach();
|
|
||||||
t->thread = thread;
|
|
||||||
chunkGenThreads.push_back(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::handleMeshGenQueue() {
|
|
||||||
//Finalize finished threads by creating a MeshChunk object from the thread data.
|
|
||||||
for (auto iter = meshGenThreads.begin(); iter != meshGenThreads.end(); ) {
|
|
||||||
MeshThreadData* threadData = (*iter);
|
|
||||||
|
|
||||||
if (threadData->done) {
|
|
||||||
//Only create the MeshChunk object if there's vertices in it.
|
|
||||||
if (!threadData->vertices->empty()) {
|
|
||||||
auto meshChunk = new MeshChunk();
|
|
||||||
meshChunk->build(threadData->vertices, threadData->indices);
|
|
||||||
|
|
||||||
glm::vec3 pos = threadData->pos * glm::vec3(CHUNK_SIZE);
|
|
||||||
meshChunk->setPosition(pos);
|
|
||||||
meshChunks.insert(std::pair<glm::vec3, MeshChunk *>(threadData->pos, meshChunk));
|
|
||||||
}
|
|
||||||
|
|
||||||
delete threadData;
|
|
||||||
iter = meshGenThreads.erase(iter);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
iter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Create new mesh gen threads if there are meshes to be made.
|
|
||||||
while (!meshGenQueue.empty() && meshGenThreads.size() < MAX_MESH_GEN_THREADS) {
|
|
||||||
auto it = meshGenQueue.begin();
|
|
||||||
meshGenQueue.erase(meshGenQueue.begin());
|
|
||||||
glm::vec3 pos = (*it);
|
|
||||||
|
|
||||||
auto t = new MeshThreadData(pos, blockChunks.at(pos), blockAtlas);
|
|
||||||
auto thread = new std::thread(meshGenThread, t);
|
|
||||||
thread->detach();
|
|
||||||
t->thread = thread;
|
|
||||||
meshGenThreads.push_back(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void World::update() {
|
void World::update() {
|
||||||
//Create / Finalize BlockChunks
|
//Create / Finalize BlockChunks
|
||||||
handleChunkGenQueue();
|
handleChunkGenQueue();
|
||||||
@ -137,13 +42,206 @@ void World::update() {
|
|||||||
handleMeshGenQueue();
|
handleMeshGenQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::handleChunkGenQueue() {
|
||||||
|
std::vector<ChunkThreadData*> finishedThreads;
|
||||||
|
|
||||||
|
for (auto threadDef : chunkThreads) {
|
||||||
|
std::unique_lock<std::mutex> lock(threadDef->lock, std::defer_lock);
|
||||||
|
lock.lock();
|
||||||
|
for (auto iter = threadDef->tasks.begin(); iter != threadDef->tasks.end();) {
|
||||||
|
auto threadData = *iter;
|
||||||
|
|
||||||
|
if (threadData->done) {
|
||||||
|
finishedThreads.push_back(threadData);
|
||||||
|
iter = threadDef->tasks.erase(iter);
|
||||||
|
} else iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!chunkGenQueue.empty() && threadDef->tasks.size() < CHUNK_THREAD_QUEUE) {
|
||||||
|
auto it = chunkGenQueue.begin();
|
||||||
|
chunkGenQueue.erase(it);
|
||||||
|
glm::vec3 pos = *it;
|
||||||
|
|
||||||
|
threadDef->tasks.push_back(new ChunkThreadData(*it, blockAtlas));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::cout << "Finished Chunks: " << finishedThreads.size() << std::endl;
|
||||||
|
|
||||||
|
for (auto iter = finishedThreads.begin(); iter != finishedThreads.end(); ) {
|
||||||
|
ChunkThreadData* threadData = *iter;
|
||||||
|
|
||||||
|
commitChunk(threadData->pos, threadData->chunk);
|
||||||
|
iter = finishedThreads.erase(iter);
|
||||||
|
delete threadData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function that runs on each ChunkGenThread in the chunk generation threadpool.
|
||||||
|
//Takes a threadDef object which contains a vector of tasks to do, and infinitely loops, completing tasks and
|
||||||
|
//re-inserting them into the vector to be further manipulated by the main thread.
|
||||||
|
void World::chunkGenThread(World::ChunkThreadDef* threadDef) {
|
||||||
|
PerlinNoise p(0);
|
||||||
|
PerlinNoise p2(10);
|
||||||
|
|
||||||
|
//Infinite loop
|
||||||
|
while (true) {
|
||||||
|
std::unique_lock<std::mutex> lock(threadDef->lock, std::defer_lock);
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
//Find the first unfinished task
|
||||||
|
World::ChunkThreadData* data = nullptr;
|
||||||
|
for (auto iter = threadDef->tasks.begin(); iter != threadDef->tasks.end(); ) {
|
||||||
|
if (!(*iter)->done) {
|
||||||
|
data = (*iter);
|
||||||
|
threadDef->tasks.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
if (data != nullptr) {
|
||||||
|
auto *blocks = new std::vector<int>();
|
||||||
|
blocks->reserve(4096);
|
||||||
|
|
||||||
|
glm::vec3 innerPos, pos;
|
||||||
|
|
||||||
|
for (int ind = 0; ind < 4096; ind++) {
|
||||||
|
ArrayTrans3D::indAssignVec(ind, &innerPos);
|
||||||
|
|
||||||
|
pos.x = innerPos.x + data->pos.x * CHUNK_SIZE;
|
||||||
|
pos.y = innerPos.y + data->pos.y * CHUNK_SIZE;
|
||||||
|
pos.z = innerPos.z + data->pos.z * CHUNK_SIZE;
|
||||||
|
|
||||||
|
double val = p.noise(pos.x / (double) 32, pos.z / (double) 32, 0) * 16;
|
||||||
|
val *= p2.noise((pos.x + 16) / (double) 48, (pos.z + 16) / (double) 48, 0) * 8;
|
||||||
|
val /= 16;
|
||||||
|
val *= pow(p.noise(pos.x / (double) 64, pos.z / (double) 64, 0), 2) * 40 + 1;
|
||||||
|
val -= pos.y;
|
||||||
|
|
||||||
|
int block = (val > 0) ? (val > 1) ? (val > 4) ? 3 : 2 : 1 : 0;
|
||||||
|
blocks->push_back(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->chunk = new BlockChunk(blocks);
|
||||||
|
data->done = true;
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
threadDef->tasks.push_back(data);
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
this_thread::sleep_for(1ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void World::handleMeshGenQueue() {
|
||||||
|
std::vector<MeshThreadData*> finishedThreads;
|
||||||
|
|
||||||
|
for (auto threadDef : meshThreads) {
|
||||||
|
std::unique_lock<std::mutex> lock(threadDef->lock, std::defer_lock);
|
||||||
|
lock.lock();
|
||||||
|
for (auto iter = threadDef->tasks.begin(); iter != threadDef->tasks.end();) {
|
||||||
|
auto threadData = *iter;
|
||||||
|
|
||||||
|
if (threadData->done) {
|
||||||
|
finishedThreads.push_back(threadData);
|
||||||
|
iter = threadDef->tasks.erase(iter);
|
||||||
|
} else iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!meshGenQueue.empty() && threadDef->tasks.size() < MESH_THREAD_QUEUE) {
|
||||||
|
auto it = meshGenQueue.begin();
|
||||||
|
meshGenQueue.erase(it);
|
||||||
|
glm::vec3 pos = *it;
|
||||||
|
|
||||||
|
threadDef->tasks.push_back(new MeshThreadData(*it, blockChunks.at(pos), blockAtlas));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Finished Meshes: " << finishedThreads.size() << std::endl;
|
||||||
|
|
||||||
|
for (auto iter = finishedThreads.begin(); iter != finishedThreads.end(); ) {
|
||||||
|
MeshThreadData* threadData = *iter;
|
||||||
|
|
||||||
|
if (!threadData->vertices->empty()) {
|
||||||
|
auto meshChunk = new MeshChunk();
|
||||||
|
meshChunk->build(threadData->vertices, threadData->indices);
|
||||||
|
|
||||||
|
glm::vec3 pos = threadData->pos * glm::vec3(CHUNK_SIZE);
|
||||||
|
meshChunk->setPosition(pos);
|
||||||
|
meshChunks.insert(std::pair<glm::vec3, MeshChunk *>(threadData->pos, meshChunk));
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = finishedThreads.erase(iter);
|
||||||
|
delete threadData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Function that runs on each MeshGenThread in the mesh generation threadpool.
|
||||||
|
//Processes tasks and returns meshes in the same vector to be handled by the main thread.
|
||||||
|
void World::meshGenThread(MeshThreadDef* threadDef) {
|
||||||
|
|
||||||
|
//Infinite loop
|
||||||
|
while (true) {
|
||||||
|
std::unique_lock<std::mutex> lock(threadDef->lock, std::defer_lock);
|
||||||
|
lock.lock();
|
||||||
|
|
||||||
|
//Find the first unfinished task
|
||||||
|
World::MeshThreadData* data = nullptr;
|
||||||
|
for (auto iter = threadDef->tasks.begin(); iter != threadDef->tasks.end(); ) {
|
||||||
|
if (!(*iter)->done) {
|
||||||
|
data = (*iter);
|
||||||
|
threadDef->tasks.erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
if (data != nullptr) {
|
||||||
|
MeshGenerator().build(data->chunk, data->atlas, *(data->vertices), *(data->indices));
|
||||||
|
data->done = true;
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
threadDef->tasks.push_back(data);
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
this_thread::sleep_for(1ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<glm::vec3, MeshChunk*, World::vec3cmp>* World::getMeshChunks() {
|
std::unordered_map<glm::vec3, MeshChunk*, World::vec3cmp>* World::getMeshChunks() {
|
||||||
return &meshChunks;
|
return &meshChunks;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
//Constructors and Destructors for the MeshThreadData / ChunkThreadData structs.
|
//Constructors and Destructors for the MeshThreadData / ChunkThreadData structs.
|
||||||
//
|
|
||||||
|
World::ChunkThreadData::ChunkThreadData(glm::vec3 pos, BlockAtlas *atlas) {
|
||||||
|
this->pos = pos;
|
||||||
|
this->atlas = atlas;
|
||||||
|
this->done = false;
|
||||||
|
this->chunk = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
World::ChunkThreadDef::ChunkThreadDef() {
|
||||||
|
thread = new std::thread(chunkGenThread, this);
|
||||||
|
|
||||||
|
sched_param sch_params;
|
||||||
|
sch_params.sched_priority = 1;
|
||||||
|
pthread_setschedparam(thread->native_handle(), SCHED_RR, &sch_params);
|
||||||
|
|
||||||
|
thread->detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
World::ChunkThreadDef::~ChunkThreadDef() {
|
||||||
|
delete thread;
|
||||||
|
}
|
||||||
|
|
||||||
World::MeshThreadData::MeshThreadData(glm::vec3 pos, BlockChunk *chunk, BlockAtlas *atlas) {
|
World::MeshThreadData::MeshThreadData(glm::vec3 pos, BlockChunk *chunk, BlockAtlas *atlas) {
|
||||||
this->pos = pos;
|
this->pos = pos;
|
||||||
this->chunk = chunk;
|
this->chunk = chunk;
|
||||||
@ -156,18 +254,18 @@ World::MeshThreadData::MeshThreadData(glm::vec3 pos, BlockChunk *chunk, BlockAtl
|
|||||||
World::MeshThreadData::~MeshThreadData() {
|
World::MeshThreadData::~MeshThreadData() {
|
||||||
delete vertices;
|
delete vertices;
|
||||||
delete indices;
|
delete indices;
|
||||||
//Delete the thread, when the deconstructor is called, the thread is done.
|
|
||||||
delete thread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
World::ChunkThreadData::ChunkThreadData(glm::vec3 pos, BlockAtlas *atlas) {
|
World::MeshThreadDef::MeshThreadDef() {
|
||||||
this->pos = pos;
|
thread = new std::thread(meshGenThread, this);
|
||||||
this->atlas = atlas;
|
|
||||||
this->done = false;
|
sched_param sch_params;
|
||||||
this->chunk = nullptr;
|
sch_params.sched_priority = 1;
|
||||||
|
pthread_setschedparam(thread->native_handle(), SCHED_RR, &sch_params);
|
||||||
|
|
||||||
|
thread->detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
World::ChunkThreadData::~ChunkThreadData() {
|
World::MeshThreadDef::~MeshThreadDef() {
|
||||||
//Delete the thread, when the deconstructor is called, the thread is done.
|
|
||||||
delete thread;
|
delete thread;
|
||||||
}
|
}
|
@ -11,36 +11,63 @@
|
|||||||
#include <vec3.hpp>
|
#include <vec3.hpp>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <bits/unordered_map.h>
|
#include <bits/unordered_map.h>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "BlockChunk.h"
|
#include "BlockChunk.h"
|
||||||
#include "MeshChunk.h"
|
#include "MeshChunk.h"
|
||||||
#include "../blocks/BlockAtlas.h"
|
#include "../blocks/BlockAtlas.h"
|
||||||
|
|
||||||
class World {
|
class World {
|
||||||
|
private:
|
||||||
|
//Predeclare structs
|
||||||
|
struct MeshThreadData;
|
||||||
|
struct MeshThreadDef;
|
||||||
|
struct ChunkThreadData;
|
||||||
|
struct ChunkThreadDef;
|
||||||
public:
|
public:
|
||||||
|
//Hashing function for glm::vec3 in maps and lists
|
||||||
struct vec3cmp {
|
struct vec3cmp {
|
||||||
size_t operator()(const glm::vec3& k)const {
|
size_t operator()(const glm::vec3& k)const {
|
||||||
return std::hash<float>()(k.x) ^ std::hash<float>()(k.y) ^ std::hash<float>()(k.z);
|
return std::hash<float>()(k.x) ^ std::hash<float>()(k.y) ^ std::hash<float>()(k.z);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
World();
|
//Functions for the thread pool implementations
|
||||||
|
static void chunkGenThread(ChunkThreadDef* threadDef);
|
||||||
|
static void meshGenThread(MeshThreadDef* threadDef);
|
||||||
|
|
||||||
explicit World(BlockAtlas* atlas);
|
explicit World(BlockAtlas* atlas);
|
||||||
|
|
||||||
void genChunk(glm::vec3 pos);
|
void genNewChunk(glm::vec3 pos);
|
||||||
void newChunk(glm::vec3 pos, BlockChunk* c);
|
void commitChunk(glm::vec3 pos, BlockChunk *c);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
std::unordered_map<glm::vec3, MeshChunk*, vec3cmp>* getMeshChunks();
|
std::unordered_map<glm::vec3, MeshChunk*, vec3cmp>* getMeshChunks();
|
||||||
|
private:
|
||||||
|
//Global lists for storing blockChunks and meshChunks
|
||||||
|
std::unordered_map<glm::vec3, BlockChunk*, vec3cmp> blockChunks;
|
||||||
|
std::unordered_map<glm::vec3, MeshChunk*, vec3cmp> meshChunks;
|
||||||
|
|
||||||
~World() = default;
|
void handleChunkGenQueue();
|
||||||
|
void handleMeshGenQueue();
|
||||||
|
|
||||||
|
const int CHUNK_THREADS = 8;
|
||||||
|
const int CHUNK_THREAD_QUEUE = 16;
|
||||||
|
std::unordered_set<glm::vec3, vec3cmp> chunkGenQueue;
|
||||||
|
std::vector<ChunkThreadDef*> chunkThreads;
|
||||||
|
|
||||||
|
const int MESH_THREADS = 8;
|
||||||
|
const int MESH_THREAD_QUEUE = 16;
|
||||||
|
std::unordered_set<glm::vec3, vec3cmp> meshGenQueue;
|
||||||
|
std::vector<MeshThreadDef*> meshThreads;
|
||||||
|
|
||||||
|
BlockAtlas* blockAtlas;
|
||||||
|
|
||||||
|
//Structs for the thread pool implementations
|
||||||
struct MeshThreadData {
|
struct MeshThreadData {
|
||||||
MeshThreadData(glm::vec3 pos, BlockChunk* chunk, BlockAtlas* atlas);
|
MeshThreadData(glm::vec3 pos, BlockChunk* chunk, BlockAtlas* atlas);
|
||||||
|
|
||||||
std::thread* thread;
|
|
||||||
|
|
||||||
glm::vec3 pos;
|
glm::vec3 pos;
|
||||||
BlockChunk* chunk;
|
BlockChunk* chunk;
|
||||||
BlockAtlas* atlas;
|
BlockAtlas* atlas;
|
||||||
@ -53,41 +80,35 @@ public:
|
|||||||
~MeshThreadData();
|
~MeshThreadData();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChunkThreadData {
|
struct MeshThreadDef {
|
||||||
ChunkThreadData(glm::vec3 pos, BlockAtlas* atlas);
|
MeshThreadDef();
|
||||||
|
|
||||||
std::thread* thread;
|
std::thread* thread;
|
||||||
|
std::mutex lock;
|
||||||
|
std::vector<MeshThreadData*> tasks;
|
||||||
|
|
||||||
|
~MeshThreadDef();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChunkThreadData {
|
||||||
|
ChunkThreadData(glm::vec3 pos, BlockAtlas* atlas);
|
||||||
|
|
||||||
glm::vec3 pos;
|
glm::vec3 pos;
|
||||||
BlockAtlas* atlas;
|
BlockAtlas* atlas;
|
||||||
|
|
||||||
bool done;
|
bool done;
|
||||||
|
|
||||||
BlockChunk* chunk;
|
BlockChunk* chunk;
|
||||||
|
|
||||||
~ChunkThreadData();
|
|
||||||
};
|
};
|
||||||
private:
|
|
||||||
std::unordered_map<glm::vec3, BlockChunk*, vec3cmp> blockChunks;
|
|
||||||
std::unordered_map<glm::vec3, MeshChunk*, vec3cmp> meshChunks;
|
|
||||||
|
|
||||||
void handleChunkGenQueue();
|
struct ChunkThreadDef {
|
||||||
void handleMeshGenQueue();
|
ChunkThreadDef();
|
||||||
|
|
||||||
//TODO: Replace this BiQueueThreadArray model with a BiQueueThreadPool model (it's in the name)
|
std::thread* thread;
|
||||||
|
std::mutex lock;
|
||||||
|
std::vector<ChunkThreadData*> tasks;
|
||||||
|
|
||||||
//Chunk Gen BiQueue Variables
|
~ChunkThreadDef();
|
||||||
const int MAX_CHUNK_GEN_THREADS = 32;
|
};
|
||||||
std::unordered_set<glm::vec3, vec3cmp> chunkGenQueue;
|
|
||||||
std::vector<ChunkThreadData*> chunkGenThreads;
|
|
||||||
|
|
||||||
//Mesh Gen BiQueue Variables
|
|
||||||
const int MAX_MESH_GEN_THREADS = 32;
|
|
||||||
std::unordered_set<glm::vec3, vec3cmp> meshGenQueue;
|
|
||||||
std::vector<MeshThreadData*> meshGenThreads;
|
|
||||||
|
|
||||||
BlockAtlas* blockAtlas;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //GLPROJECT_WORLD_H
|
#endif //GLPROJECT_WORLD_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user