diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 6ed34baa..182bed6f 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -272,15 +272,15 @@ public: LoaderWorker(AssetsLoader* loader) : loader(loader) { } - assetload::postfunc operator()(const std::shared_ptr& entry + assetload::postfunc operator()(const aloader_entry& entry ) override { - aloader_func loadfunc = loader->getLoader(entry->tag); + aloader_func loadfunc = loader->getLoader(entry.tag); return loadfunc( loader, loader->getPaths(), - entry->filename, - entry->alias, - entry->config + entry.filename, + entry.alias, + entry.config ); } }; @@ -290,14 +290,13 @@ std::shared_ptr AssetsLoader::startTask(runnable onDone) { std::make_shared>( "assets-loader-pool", [=]() { return std::make_shared(this); }, - [=](assetload::postfunc& func) { func(assets); } + [=](const assetload::postfunc& func) { func(assets); } ); pool->setOnComplete(std::move(onDone)); while (!entries.empty()) { - const aloader_entry& entry = entries.front(); - auto ptr = std::make_shared(entry); - pool->enqueueJob(ptr); + aloader_entry entry = std::move(entries.front()); entries.pop(); + pool->enqueueJob(std::move(entry)); } return pool; } diff --git a/src/assets/AssetsLoader.hpp b/src/assets/AssetsLoader.hpp index 602d841a..2321f9a3 100644 --- a/src/assets/AssetsLoader.hpp +++ b/src/assets/AssetsLoader.hpp @@ -43,8 +43,8 @@ using aloader_func = std::function< struct aloader_entry { AssetType tag; - const std::string filename; - const std::string alias; + std::string filename; + std::string alias; std::shared_ptr config; }; diff --git a/src/files/WorldConverter.cpp b/src/files/WorldConverter.cpp index 46b85868..f9484142 100644 --- a/src/files/WorldConverter.cpp +++ b/src/files/WorldConverter.cpp @@ -27,8 +27,8 @@ public: : converter(std::move(converter)) { } - int operator()(const std::shared_ptr& task) override { - converter->convert(*task); + int operator()(const ConvertTask& task) override { + converter->convert(task); return 0; } }; @@ -169,10 +169,10 @@ std::shared_ptr WorldConverter::startTask( ); auto& converterTasks = converter->tasks; while (!converterTasks.empty()) { - const ConvertTask& task = converterTasks.front(); - auto ptr = std::make_shared(task); - pool->enqueueJob(ptr); + ConvertTask task = std::move(converterTasks.front()); converterTasks.pop(); + pool->enqueueJob(std::move(task)); + } pool->setOnComplete([=]() { converter->write(); diff --git a/src/graphics/core/Mesh.cpp b/src/graphics/core/Mesh.cpp index ac4e2b14..78380ae1 100644 --- a/src/graphics/core/Mesh.cpp +++ b/src/graphics/core/Mesh.cpp @@ -4,6 +4,21 @@ int Mesh::meshesCount = 0; int Mesh::drawCalls = 0; +inline size_t calc_vertex_size(const vattr* attrs) { + size_t vertexSize = 0; + for (int i = 0; attrs[i].size; i++) { + vertexSize += attrs[i].size; + } + return vertexSize; +} + +Mesh::Mesh(const MeshData& data) + : Mesh(data.vertices.data(), + data.vertices.size() / calc_vertex_size(data.attrs.data()), + data.indices.data(), + data.indices.size(), + data.attrs.data()) {} + Mesh::Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const vattr* attrs) : ibo(0), vertices(vertices), diff --git a/src/graphics/core/Mesh.hpp b/src/graphics/core/Mesh.hpp index c94154a6..87c8e69b 100644 --- a/src/graphics/core/Mesh.hpp +++ b/src/graphics/core/Mesh.hpp @@ -1,11 +1,9 @@ #pragma once #include -#include "typedefs.hpp" -struct vattr { - ubyte size; -}; +#include "typedefs.hpp" +#include "MeshData.hpp" class Mesh { unsigned int vao; @@ -15,6 +13,7 @@ class Mesh { size_t indices; size_t vertexSize; public: + Mesh(const MeshData& data); Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const vattr* attrs); Mesh(const float* vertexBuffer, size_t vertices, const vattr* attrs) : Mesh(vertexBuffer, vertices, nullptr, 0, attrs) {}; diff --git a/src/graphics/core/MeshData.hpp b/src/graphics/core/MeshData.hpp new file mode 100644 index 00000000..62b32903 --- /dev/null +++ b/src/graphics/core/MeshData.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include "typedefs.hpp" +#include "util/Buffer.hpp" + +/// @brief Vertex attribute info +struct vattr { + ubyte size; +}; + +/// @brief Raw mesh data structure +struct MeshData { + util::Buffer vertices; + util::Buffer indices; + util::Buffer attrs; + + MeshData() = default; + + /// @param vertices vertex data buffer + /// @param indices nullable indices buffer + /// @param attrs vertex attribute sizes (must be null-terminated) + MeshData( + util::Buffer vertices, + util::Buffer indices, + util::Buffer attrs + ) : vertices(std::move(vertices)), + indices(std::move(indices)), + attrs(std::move(attrs)) {} +}; diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index e457fb69..eb3a134a 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -531,7 +531,18 @@ void BlocksRenderer::build(const Chunk* chunk, const ChunksStorage* chunks) { render(voxels); } -std::shared_ptr BlocksRenderer::createMesh() { +MeshData BlocksRenderer::createMesh() { + const vattr attrs[]{ {3}, {2}, {1}, {0} }; + return MeshData( + util::Buffer(vertexBuffer.get(), vertexOffset), + util::Buffer(indexBuffer.get(), indexSize), + util::Buffer({{3}, {2}, {1}, {0}}) + ); +} + +std::shared_ptr BlocksRenderer::render(const Chunk* chunk, const ChunksStorage* chunks) { + build(chunk, chunks); + const vattr attrs[]{ {3}, {2}, {1}, {0} }; size_t vcount = vertexOffset / BlocksRenderer::VERTEX_SIZE; return std::make_shared( @@ -539,11 +550,6 @@ std::shared_ptr BlocksRenderer::createMesh() { ); } -std::shared_ptr BlocksRenderer::render(const Chunk* chunk, const ChunksStorage* chunks) { - build(chunk, chunks); - return createMesh(); -} - VoxelsVolume* BlocksRenderer::getVoxelsBuffer() const { return voxelsBuffer.get(); } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index e0da218c..60aa3a07 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -10,6 +10,7 @@ #include "voxels/Block.hpp" #include "voxels/Chunk.hpp" #include "voxels/VoxelsVolume.hpp" +#include "graphics/core/MeshData.hpp" class Content; class Mesh; @@ -148,7 +149,7 @@ public: void build(const Chunk* chunk, const ChunksStorage* chunks); std::shared_ptr render(const Chunk* chunk, const ChunksStorage* chunks); - std::shared_ptr createMesh(); + MeshData createMesh(); VoxelsVolume* getVoxelsBuffer() const; bool isCancelled() const { diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index 04bcb548..f5fb7f89 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -12,7 +12,7 @@ static debug::Logger logger("chunks-render"); -class RendererWorker : public util::Worker { +class RendererWorker : public util::Worker, RendererResult> { Level* level; BlocksRenderer renderer; public: @@ -27,7 +27,13 @@ public: RendererResult operator()(const std::shared_ptr& chunk) override { renderer.build(chunk.get(), level->chunksStorage.get()); - return RendererResult {glm::ivec2(chunk->x, chunk->z), &renderer}; + if (renderer.isCancelled()) { + return RendererResult { + glm::ivec2(chunk->x, chunk->z), true, MeshData()}; + } + auto meshData = renderer.createMesh(); + return RendererResult { + glm::ivec2(chunk->x, chunk->z), false, std::move(meshData)}; } }; @@ -39,14 +45,13 @@ ChunksRenderer::ChunksRenderer( threadPool( "chunks-render-pool", [=](){return std::make_shared(level, cache, settings);}, - [=](RendererResult& mesh){ - if (!mesh.renderer->isCancelled()) { - meshes[mesh.key] = mesh.renderer->createMesh(); + [=](RendererResult& result){ + if (!result.cancelled) { + meshes[result.key] = std::make_shared(result.meshData); } - inwork.erase(mesh.key); + inwork.erase(result.key); }, settings->graphics.chunkMaxRenderers.get()) { - threadPool.setStandaloneResults(false); threadPool.setStopOnFail(false); renderer = std::make_unique( settings->graphics.chunkMaxVertices.get(), diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index 89691c4e..62d07280 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -9,6 +9,7 @@ #include "voxels/Block.hpp" #include "voxels/ChunksStorage.hpp" #include "util/ThreadPool.hpp" +#include "graphics/core/MeshData.hpp" class Mesh; class Chunk; @@ -19,7 +20,8 @@ struct EngineSettings; struct RendererResult { glm::ivec2 key; - BlocksRenderer* renderer; + bool cancelled; + MeshData meshData; }; class ChunksRenderer { @@ -28,7 +30,7 @@ class ChunksRenderer { std::unordered_map> meshes; std::unordered_map inwork; - util::ThreadPool threadPool; + util::ThreadPool, RendererResult> threadPool; public: ChunksRenderer( Level* level, diff --git a/src/util/Buffer.hpp b/src/util/Buffer.hpp index a721e646..f7bf3ff6 100644 --- a/src/util/Buffer.hpp +++ b/src/util/Buffer.hpp @@ -2,6 +2,7 @@ #include #include +#include namespace util { /// @brief Template similar to std::unique_ptr stores a buffer with its size @@ -11,6 +12,8 @@ namespace util { std::unique_ptr ptr; size_t length; public: + Buffer() = default; + Buffer(size_t length) : ptr(std::make_unique(length)), length(length) { } @@ -23,7 +26,23 @@ namespace util { Buffer(const T* src, size_t length) : ptr(std::make_unique(length)), length(length) { - std::memcpy(ptr.get(), src, length); + std::memcpy(ptr.get(), src, length * sizeof(T)); + } + + Buffer(std::initializer_list values) + : ptr(std::make_unique(values.size())), + length(values.size()) { + std::copy(values.begin(), values.end(), ptr.get()); + } + + Buffer(std::nullptr_t) noexcept : ptr(nullptr), length(0) {} + + inline bool operator==(std::nullptr_t) const noexcept { + return ptr == nullptr; + } + + inline bool operator!=(std::nullptr_t) const noexcept { + return ptr != nullptr; } T& operator[](long long index) { diff --git a/src/util/ThreadPool.hpp b/src/util/ThreadPool.hpp index 3bc7f86e..98ebcce5 100644 --- a/src/util/ThreadPool.hpp +++ b/src/util/ThreadPool.hpp @@ -17,7 +17,7 @@ namespace util { template struct ThreadPoolResult { - std::shared_ptr job; + J job; std::condition_variable& variable; int workerIndex; bool& locked; @@ -29,13 +29,13 @@ namespace util { public: Worker() = default; virtual ~Worker() = default; - virtual R operator()(const std::shared_ptr&) = 0; + virtual R operator()(const T&) = 0; }; template class ThreadPool : public Task { debug::Logger logger; - std::queue> jobs; + std::queue jobs; std::queue> results; std::mutex resultsMutex; std::vector threads; @@ -43,7 +43,7 @@ namespace util { std::mutex jobsMutex; std::vector> workersBlocked; consumer resultConsumer; - consumer&> onJobFailed = nullptr; + consumer onJobFailed = nullptr; runnable onComplete = nullptr; std::atomic busyWorkers = 0; std::atomic jobsDone = 0; @@ -57,7 +57,7 @@ namespace util { std::mutex mutex; bool locked = false; while (working) { - std::shared_ptr job; + T job; { std::unique_lock lock(jobsMutex); jobsMutexCondition.wait(lock, [this] { @@ -66,7 +66,7 @@ namespace util { if (!working || failed) { break; } - job = jobs.front(); + job = std::move(jobs.front()); jobs.pop(); busyWorkers++; @@ -229,10 +229,10 @@ namespace util { } } - void enqueueJob(const std::shared_ptr& job) { + void enqueueJob(T job) { { std::lock_guard lock(jobsMutex); - jobs.push(job); + jobs.push(std::move(job)); } jobsMutexCondition.notify_one(); }