1
0
Fork 0

Merge workers and other fixs

This commit is contained in:
May B. 2020-08-05 15:14:57 +02:00
parent 310efea675
commit bce746ca01
24 changed files with 115 additions and 94 deletions

View File

@ -43,7 +43,7 @@
- [ ] ZeroMQ
- [x] Logger
- [ ] FastNoiseSIMD / HastyNoise double precision
- [ ] Generation identifier
- [x] Generational identifier
- [ ] Limit map usage
## Rendering

View File

@ -6,5 +6,5 @@ layout(location = 0) out vec4 color;
in vec4 Color;
void main(){
color = Color;
color = vec4(Color.xyz, .5);
}

View File

@ -10,14 +10,14 @@ uniform sampler2DArray HOSAtlas;
uniform mat4 View;
uniform vec3 FogColor;
#ifdef BLEND
#ifdef GEOMETRY
in GeometryData
#else
in VertexData
#endif
{
vec3 Position_modelspace;
#ifdef BLEND
#ifdef GEOMETRY
flat uint Materials[3];
vec3 MaterialRatio;
#else
@ -39,6 +39,7 @@ vec3 expand(vec3 v) {
}
vec4 getTexture(sampler2DArray sample, vec2 UV) {
#ifdef GEOMETRY
#ifdef BLEND
vec4 colx = texture(sample, vec3(UV, vs.Materials[0]));
if(vs.Materials[1] == vs.Materials[0]) {
@ -50,6 +51,12 @@ vec4 getTexture(sampler2DArray sample, vec2 UV) {
vs.Materials[2] == vs.Materials[1] ? mix(coly, colx, vs.MaterialRatio.x) :
colx * vs.MaterialRatio.x + coly * vs.MaterialRatio.y + texture(sample, vec3(UV, vs.Materials[2])) * vs.MaterialRatio.z);
}
#else
int mainMaterial = vs.MaterialRatio.x >= vs.MaterialRatio.y ?
(vs.MaterialRatio.x >= vs.MaterialRatio.z ? 0 : 2) :
(vs.MaterialRatio.y >= vs.MaterialRatio.z ? 1 : 2);
return texture(sample, vec3(UV, vs.Materials[mainMaterial]));
#endif
#else
return texture(sample, vec3(UV, vs.Material));
#endif

View File

@ -26,7 +26,9 @@ namespace contouring {
/// Display ImGui config
virtual void onGui() = 0;
/// Get options
virtual std::string getOptions() = 0;
virtual std::string getOptions() const = 0;
// Get camera recommended far range
virtual std::pair<float, float> getFarRange() const = 0;
/// Get buffers in frustum with model matrices
/// @note buffers invalidated after update

View File

@ -44,7 +44,7 @@ namespace contouring {
loadDistance = opt["load_distance"].value_or(loadDistance);
keepDistance = opt["keep_distance"].value_or(keepDistance);
}
std::string AbstractFlat::getOptions() {
std::string AbstractFlat::getOptions() const {
std::ostringstream ss;
ss << toml::table({
{"load_distance", loadDistance},
@ -52,6 +52,9 @@ namespace contouring {
});
return ss.str();
}
std::pair<float, float> AbstractFlat::getFarRange() const {
return std::make_pair((loadDistance - 1.5) * CHUNK_LENGTH, (keepDistance + .5) * CHUNK_LENGTH);
}
void AbstractFlat::onGui() {
ImGui::SliderInt("Load Distance", &loadDistance, 1, keepDistance);

View File

@ -13,7 +13,8 @@ namespace contouring {
/// Display ImGui config
void onGui() override;
std::string getOptions() override;
std::string getOptions() const override;
std::pair<float, float> getFarRange() const override;
/// Get buffers in frustum with model matrices
/// @note buffers invalidated after update
@ -22,8 +23,7 @@ namespace contouring {
protected:
size_t clear(const voxel_pos &, const world::area_map &areas);
//MAYBE: store position copy
robin_hood::unordered_flat_map<area_id, robin_hood::pair<area_pos, robin_hood::unordered_flat_map<chunk_pos, buffer::Abstract *>>> buffers;
robin_hood::unordered_map<area_id, robin_hood::pair<area_pos, robin_hood::unordered_map<chunk_pos, buffer::Abstract *>>> buffers;
int loadDistance = 3;
int keepDistance = 4;

View File

@ -13,7 +13,8 @@ namespace contouring {
void onUpdate(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &, geometry::Faces) override {}
void onNotify(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &) override {}
void onGui() override { }
std::string getOptions() override { return ""; }
std::string getOptions() const override { return ""; }
std::pair<float, float> getFarRange() const override { return std::make_pair(0, 0); }
void getModels(std::vector<std::pair<glm::mat4, buffer::Abstract *const>> &, const std::optional<geometry::Frustum>&, const glm::llvec3&, int) override { }
};
}

View File

@ -30,7 +30,7 @@ namespace contouring {
}
FlatDualMC::~FlatDualMC() {
running = false;
loadQueue.notify();
loadQueue.notify_all();
for(auto& worker: workers) {
if (worker.joinable())
@ -38,7 +38,7 @@ namespace contouring {
}
}
std::string FlatDualMC::getOptions() {
std::string FlatDualMC::getOptions() const {
std::ostringstream ss;
ss << toml::table({
{"load_distance", loadDistance},

View File

@ -9,8 +9,6 @@
#include "../render/buffer/ShortIndexed.hpp"
#include <thread>
#define REPORT_BUFFER_SIZE 128
using namespace data;
namespace contouring {
/// Dual Marching Cube 1:1 contouring
@ -23,7 +21,7 @@ namespace contouring {
void onGui() override;
std::string getOptions() override;
std::string getOptions() const override;
/// Chunk data change
void onUpdate(const area_<chunk_pos> &, const chunk_pos &, const world::ChunkContainer &, geometry::Faces) override;

View File

@ -28,7 +28,7 @@ namespace contouring {
}
FlatSurroundingBox::~FlatSurroundingBox() {
running = false;
loadQueue.notify();
loadQueue.notify_all();
for(auto& worker: workers) {
if (worker.joinable())

View File

@ -9,8 +9,6 @@
#include "../render/buffer/ShortIndexed.hpp"
#include <thread>
#define REPORT_BUFFER_SIZE 128
using namespace data;
namespace contouring {
/// Stupid cubes 1:1 contouring

View File

@ -14,7 +14,7 @@
#include <cstdint>
// stl includes
#include <unordered_map>
#include <robin_hood.h>
#include <vector>
namespace dualmc {
@ -211,7 +211,7 @@ protected:
};
/// Hash map for shared vertex index computations
std::unordered_map<DualPointKey,QuadIndexType,DualPointKeyHash> pointToIndex;
robin_hood::unordered_map<DualPointKey,QuadIndexType,DualPointKeyHash> pointToIndex;
};
// inline function definitions

View File

@ -1,6 +1,6 @@
#pragma once
#include <unordered_map>
#include <robin_hood.h>
#include <vector>
#include <GL/glew.h>
@ -37,7 +37,7 @@ public:
private:
GLFWwindow *window;
std::unordered_map<Input, int> Map = {
robin_hood::unordered_map<Input, int> Map = {
{Input::Forward, GLFW_KEY_W},
{Input::Backward, GLFW_KEY_S},
{Input::Left, GLFW_KEY_A},
@ -51,7 +51,7 @@ private:
const std::vector<Input> Toggles = {
Input::Mouse, Input::Debug, Input::Throw
};
std::unordered_map<Input, bool> Previous;
robin_hood::unordered_map<Input, bool> Previous;
bool PreviousLeft;
bool PreviousRight;

View File

@ -2,7 +2,6 @@
#include <tuple>
#include <vector>
#include <unordered_set>
#include <robin_hood.h>
#include <mutex>
#include <condition_variable>
@ -59,9 +58,12 @@ namespace data {
return map.size();
}
void notify() {
void notify_all() {
cv.notify_all();
}
void notify_one() {
cv.notify_one();
}
void wait() {
std::unique_lock<std::mutex> lock(mutex);
@ -121,9 +123,12 @@ namespace data {
return set.size();
}
void notify() {
void notify_all() {
cv.notify_all();
}
void notify_one() {
cv.notify_one();
}
void wait() {
std::unique_lock<std::mutex> lock(mutex);

View File

@ -47,9 +47,12 @@ namespace data {
return queue.size();
}
void notify() {
void notify_all() {
cv.notify_all();
}
void notify_one() {
cv.notify_one();
}
void wait() {
std::unique_lock<std::mutex> lock(mutex);

View File

@ -62,9 +62,12 @@ namespace data {
return set.size();
}
void notify() {
void notify_all() {
cv.notify_all();
}
void notify_one() {
cv.notify_one();
}
void wait() {
std::unique_lock<std::mutex> lock(mutex);

View File

@ -79,8 +79,14 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
changeRenderer |= ImGui::Checkbox("PBR", &options.renderer.main.pbr);
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Triplanar", &options.renderer.main.triplanar);
changeRenderer |= ImGui::Checkbox("Geometry", &options.renderer.main.geometry);
ImGui::SameLine();
changeRenderer |= ImGui::Checkbox("Blend", &options.renderer.main.blend);
if(options.renderer.main.geometry) {
changeRenderer |= ImGui::Checkbox("Blend", &options.renderer.main.blend);
} else {
ImGui::TextDisabled("Blend");
}
changeRenderer |= ImGui::Checkbox("Fog", &options.renderer.main.fog);
ImGui::SameLine();
@ -113,11 +119,6 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
if (ImGui::SliderInt("Load distance", &options.world.loadDistance, 1, options.world.keepDistance) |
ImGui::SliderInt("Keep distance", &options.world.keepDistance, options.world.loadDistance + 1, 21)) {
actions = actions | Actions::World;
const auto far = std::clamp(options.camera.far, (options.world.loadDistance - 1.5f) * CHUNK_LENGTH / options.voxel_density, (options.world.keepDistance + .5f) * CHUNK_LENGTH / options.voxel_density);
if(far != options.camera.far) {
options.camera.far = far;
actions = actions | Actions::Camera;
}
}
if(ImGui::SliderInt("Voxel density", &options.voxel_density, 1, CHUNK_LENGTH * REGION_LENGTH)) {
options.voxel_density = pow(2, ceil(log(options.voxel_density) / log(2)));
@ -145,23 +146,31 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
ImGui::End();
}
if (options.show_debug_controls) {
ImGui::Begin("Debug: Controls", &options.show_debug_controls, ImGuiWindowFlags_AlwaysAutoResize);
const auto p = state.position.as_voxel(options.voxel_density);
ImGui::Text("Position: (%lld, %lld, %lld)", p.x, p.y, p.z);
ImGui::Separator();
{
bool changePerspective = false;
changePerspective |= ImGui::SliderAngle("FoV", &options.camera.fov, 30, 110);
changePerspective |= ImGui::SliderFloat("Near", &options.camera.near, 0.01, 10);
changePerspective |= ImGui::SliderFloat("Far", &options.camera.far, (options.world.loadDistance - 1.5) * CHUNK_LENGTH / options.voxel_density, (options.world.keepDistance + .5) * CHUNK_LENGTH / options.voxel_density);
changePerspective |= ImGui::SliderFloat("Move speed", &options.camera.speed, 0.1, 50);
changePerspective |= ImGui::SliderInt("Sensibility", &options.camera.sensibility, 1, 100, "%d%%");
if(changePerspective) {
actions = actions | Actions::Camera;
{
const auto farRange = state.contouring->getFarRange();
if (options.show_debug_controls) {
ImGui::Begin("Debug: Controls", &options.show_debug_controls, ImGuiWindowFlags_AlwaysAutoResize);
const auto p = state.position.as_voxel(options.voxel_density);
ImGui::Text("Position: (%lld, %lld, %lld)", p.x, p.y, p.z);
ImGui::Separator();
{
bool changePerspective = false;
changePerspective |= ImGui::SliderAngle("FoV", &options.camera.fov, 30, 110);
changePerspective |= ImGui::SliderFloat("Near", &options.camera.near, 0.01, 10);
changePerspective |= ImGui::SliderFloat("Far", &options.camera.far, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
changePerspective |= ImGui::SliderFloat("Move speed", &options.camera.speed, 0.1, 50);
changePerspective |= ImGui::SliderInt("Sensibility", &options.camera.sensibility, 1, 100, "%d%%");
if(changePerspective) {
actions = actions | Actions::Camera;
}
}
ImGui::End();
}
const auto far = std::clamp(options.camera.far, farRange.first / options.voxel_density, farRange.second / options.voxel_density);
if(far != options.camera.far) {
options.camera.far = far;
actions = actions | Actions::Camera;
}
ImGui::End();
}
if (options.editor_show) {

View File

@ -13,13 +13,16 @@ MainProgram::MainProgram(const MainProgram::options& opts): Program() {
flags.emplace_back("TRIPLANAR");
if (opts.fog)
flags.emplace_back("FOG");
if (opts.blend)
flags.emplace_back("BLEND");
if (opts.geometry) {
flags.emplace_back("GEOMETRY");
if (opts.blend)
flags.emplace_back("BLEND");
}
std::vector<Shader*> shaders;
shaders.push_back(loadShader(GL_VERTEX_SHADER, flags));
shaders.push_back(loadShader(GL_FRAGMENT_SHADER, flags));
if (opts.blend)
if (opts.geometry)
shaders.push_back(loadShader(GL_GEOMETRY_SHADER, flags));
load(shaders);

View File

@ -12,8 +12,10 @@ namespace pass {
bool pbr = true;
/// Triplanar texture mapping
bool triplanar = false;
/// Blend voxel with mixed materials
bool blend = true;
/// Active geometry pass
bool geometry = true;
/// Blend voxel with mixed materials (requires geometry)
bool blend = false;
/// Depth fog
bool fog = true;
};

View File

@ -3,7 +3,6 @@
#define UI_MARGIN 5
#define MIN_FPS 24
#define MAX_FPS 240
#define REPORT_BUFFER_SIZE 128
#include <toml.h>
#include <fstream>
@ -42,6 +41,7 @@ struct options {
renderer.mipMapLOD = config["render"]["texture_quality"].value_or(renderer.mipMapLOD);
renderer.main.pbr = config["render"]["pbr"].value_or(renderer.main.pbr);
renderer.main.triplanar = config["render"]["triplanar"].value_or(renderer.main.triplanar);
renderer.main.geometry = config["render"]["geometry"].value_or(renderer.main.geometry);
renderer.main.blend = config["render"]["blend"].value_or(renderer.main.blend);
renderer.main.fog = config["render"]["fog"].value_or(renderer.main.fog);
const std::string fog = config["render"]["fog_color"].value_or(std::string{"#000000"});
@ -92,6 +92,7 @@ struct options {
{"texture_quality", renderer.mipMapLOD},
{"pbr", renderer.main.pbr},
{"triplanar", renderer.main.triplanar},
{"geometry", renderer.main.geometry},
{"blend", renderer.main.blend},
{"fog", renderer.main.fog},
{"fog_color", toHexa(renderer.clear_color)},

View File

@ -55,21 +55,20 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
entities.emplace(nullptr, glm::vec3(1), glm::vec3(2));
// Load workers
// Workers
for (size_t i = 0; i < 4; i++) {
loadWorkers.emplace_back([&] {
const auto ctx = dicts.make_reader();
workers.emplace_back([&] {
const auto read_ctx = dicts.make_reader();
const auto write_ctx = dicts.make_writer();
while (running) {
std::pair<area_<chunk_pos>, std::shared_ptr<Area>> task;
loadQueue.wait();
if (loadQueue.pop(task)) {
if (std::pair<area_<chunk_pos>, std::shared_ptr<Area>> task; loadQueue.pop(task)) {
//MAYBE: loadQueue.take to avoid duplicated work on fast move
rmt_ScopedCPUSample(ProcessLoad, 0);
const auto &pos = task.first;
const auto rcPos = glm::split(pos.second);
const auto reg = task.second->getRegion(folderPath, std::make_pair(pos.first, rcPos.first));
Region::data data;
if(reg->read(rcPos.second, ctx, data)) {
if(reg->read(rcPos.second, read_ctx, data)) {
rmt_ScopedCPUSample(ProcessRead, 0);
vec_istream idata(data);
std::istream iss(&idata);
@ -78,26 +77,18 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
rmt_ScopedCPUSample(ProcessGenerate, 0);
loadedQueue.push({pos, std::make_shared<Chunk>(pos.second, task.second->getGenerator())});
}
}
}
});
}
// Save workers
for (size_t i = 0; i < 2; i++) {
saveWorkers.emplace_back([&] {
const auto ctx = dicts.make_writer();
while (running) {
save_task_t task;
saveQueue.wait();
if (saveQueue.pop(task) && task.second.second->isModified()) {
} else if(save_task_t task; saveQueue.pop(task)) {
//MAYBE: queue.take to avoid concurent write or duplicated work on fast move
rmt_ScopedCPUSample(ProcessSave, 0);
std::ostringstream out;
task.second.second->write(out);
const auto rcPos = glm::split(task.second.first);
const auto reg = task.first.second->getRegion(folderPath, std::make_pair(task.first.first, rcPos.first));
reg->write(rcPos.second, ctx, out.str());
if(task.second.second->isModified()) {
std::ostringstream out;
task.second.second->write(out);
const auto rcPos = glm::split(task.second.first);
const auto reg = task.first.second->getRegion(folderPath, std::make_pair(task.first.first, rcPos.first));
reg->write(rcPos.second, write_ctx, out.str());
}
} else {
loadQueue.wait();
}
}
});
@ -108,9 +99,12 @@ Universe::~Universe() {
// Save all
for(auto& area: areas) {
for(const auto& chunk: area.second->getChunks())
for(const auto& chunk: area.second->getChunks()) {
saveQueue.emplace(area, chunk);
}
}
loadQueue.notify_all();
if (auto size = saveQueue.size(); size > 0) {
LOG_I("Saving " << size << " chunks");
const auto SAVE_CHECK_TIME = 500;
@ -124,14 +118,9 @@ Universe::~Universe() {
saveAreas();
running = false;
loadQueue.notify();
saveQueue.notify();
loadQueue.notify_all();
for (auto &worker: loadWorkers) {
if (worker.joinable())
worker.join();
}
for (auto &worker: saveWorkers) {
for (auto &worker: workers) {
if (worker.joinable())
worker.join();
}

View File

@ -12,8 +12,6 @@
#include "Area.hpp"
#include "Voxel.hpp"
#define REPORT_BUFFER_SIZE 128
namespace contouring {
class Abstract;
};
@ -109,11 +107,10 @@ namespace world {
data::generational::vector<Entity> entities;
bool running = true;
std::vector<std::thread> loadWorkers;
std::vector<std::thread> workers;
safe_priority_queue_map<area_<chunk_pos>, std::shared_ptr<Area>, int, area_hash> loadQueue; //NOTE: consider Area const (getRegion uses mutex)
safe_queue<robin_hood::pair<area_<chunk_pos>, std::shared_ptr<Chunk>>> loadedQueue;
std::vector<std::thread> saveWorkers;
using save_task_t = std::pair<area_it_t, robin_hood::pair<chunk_pos, std::shared_ptr<Chunk>>>;
data::safe_queue<save_task_t> saveQueue; //NOTE: consider Area and Chunk const

View File

@ -27,7 +27,7 @@ namespace world {
std::shared_mutex mutex;
std::ifstream file;
robin_hood::unordered_flat_map<region_chunk_pos, std::pair<ushort, std::streampos>> index;
robin_hood::unordered_map<region_chunk_pos, std::pair<ushort, std::streampos>> index;
void load();
};

View File

@ -27,7 +27,7 @@ namespace world {
//TODO: use tickets to remove unused regions
std::shared_mutex mutex;
robin_hood::unordered_flat_map<region_chunk_pos, data*> content;
robin_hood::unordered_map<region_chunk_pos, data*> content;
bool changed = false;
void load();