reduce copies in ThreadPool

This commit is contained in:
MihailRis 2025-12-25 23:39:11 +03:00
parent d14f5d6dfd
commit 79eb185530
7 changed files with 35 additions and 26 deletions

View file

@ -354,7 +354,7 @@ std::shared_ptr<Task> AssetsLoader::startTask(runnable onDone) {
std::make_shared<util::ThreadPool<aloader_entry, assetload::postfunc>>( std::make_shared<util::ThreadPool<aloader_entry, assetload::postfunc>>(
"assets-loader-pool", "assets-loader-pool",
[=]() { return std::make_shared<LoaderWorker>(this); }, [=]() { return std::make_shared<LoaderWorker>(this); },
[this](const assetload::postfunc& func) { func(&assets); } [this](assetload::postfunc&& func) { func(&assets); }
); );
pool->setOnComplete(std::move(onDone)); pool->setOnComplete(std::move(onDone));
while (!entries.empty()) { while (!entries.empty()) {

View file

@ -785,7 +785,7 @@ ChunkMesh BlocksRenderer::render(
IndexBufferData {indexBuffer.get(), indexCount}, IndexBufferData {indexBuffer.get(), indexCount},
IndexBufferData {denseIndexBuffer.get(), denseIndexCount}, IndexBufferData {denseIndexBuffer.get(), denseIndexCount},
} }
), std::move(sortingMesh)}; ), std::move(sortingMesh), nullptr};
} }
size_t BlocksRenderer::getMemoryConsumption() const { size_t BlocksRenderer::getMemoryConsumption() const {

View file

@ -21,7 +21,7 @@ class VoxelsVolume;
class ContentGfxCache; class ContentGfxCache;
struct UVRegion; struct UVRegion;
class BlocksRenderer { class BlocksRenderer final {
public: public:
BlocksRenderer( BlocksRenderer(
size_t capacity, size_t capacity,
@ -29,7 +29,7 @@ public:
const ContentGfxCache& cache, const ContentGfxCache& cache,
const EngineSettings& settings const EngineSettings& settings
); );
virtual ~BlocksRenderer(); ~BlocksRenderer();
void build(const Chunk* chunk, const VoxelsVolume& volume); void build(const Chunk* chunk, const VoxelsVolume& volume);
ChunkMesh render( ChunkMesh render(

View file

@ -73,14 +73,16 @@ ChunksRenderer::ChunksRenderer(
*level, cache, settings *level, cache, settings
); );
}, },
[&](RendererResult& result) { [&](RendererResult&& result) {
if (!result.cancelled) { if (!result.cancelled) {
auto meshData = std::move(result.meshData); auto meshData = std::move(result.meshData);
meshes[result.key] = ChunkMesh { auto chunk = std::make_unique<Mesh<ChunkVertex>>(meshData.mesh);
std::make_unique<Mesh<ChunkVertex>>(meshData.mesh), meshes[result.key] = ChunkMesh {
std::move(meshData.sortingMesh)}; std::move(chunk),
} std::move(meshData.sortingMesh),
inwork.erase(result.key); nullptr};
}
inwork.erase(result.key);
}, },
settings.graphics.chunkMaxRenderers.get() settings.graphics.chunkMaxRenderers.get()
) { ) {
@ -130,8 +132,8 @@ const Mesh<ChunkVertex>* ChunksRenderer::render(
auto voxelsBuffer = prepareVoxelsVolume(*chunk); auto voxelsBuffer = prepareVoxelsVolume(*chunk);
auto mesh = renderer->render(chunk.get(), *voxelsBuffer); auto mesh = renderer->render(chunk.get(), *voxelsBuffer);
meshes[key] = meshes[key] = ChunkMesh {
ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)}; std::move(mesh.mesh), std::move(mesh.sortingMeshData), nullptr};
return meshes[key].mesh.get(); return meshes[key].mesh.get();
} }
if (inwork.find(key) != inwork.end()) { if (inwork.find(key) != inwork.end()) {
@ -174,7 +176,7 @@ const Mesh<ChunkVertex>* ChunksRenderer::getOrRender(
} }
void ChunksRenderer::update() { void ChunksRenderer::update() {
threadPool.update(); threadPool.pullResults();
} }
const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk( const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(

View file

@ -1,14 +1,14 @@
#pragma once #pragma once
#include "graphics/core/MeshData.hpp"
#include "util/Buffer.hpp"
#include <vector> #include <vector>
#include <array> #include <array>
#include <memory> #include <memory>
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include "graphics/core/MeshData.hpp"
#include "util/Buffer.hpp"
/// @brief Chunk mesh vertex format /// @brief Chunk mesh vertex format
struct ChunkVertex { struct ChunkVertex {
glm::vec3 position; glm::vec3 position;
@ -49,5 +49,5 @@ struct ChunkMeshData {
struct ChunkMesh { struct ChunkMesh {
std::unique_ptr<Mesh<ChunkVertex>> mesh; std::unique_ptr<Mesh<ChunkVertex>> mesh;
SortingMeshData sortingMeshData; SortingMeshData sortingMeshData;
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh = nullptr; std::unique_ptr<Mesh<ChunkVertex> > sortedMesh;
}; };

View file

@ -42,7 +42,7 @@ namespace util {
std::condition_variable jobsMutexCondition; std::condition_variable jobsMutexCondition;
std::mutex jobsMutex; std::mutex jobsMutex;
std::vector<std::unique_lock<std::mutex>> workersBlocked; std::vector<std::unique_lock<std::mutex>> workersBlocked;
consumer<R&> resultConsumer; consumer<R&&> resultConsumer;
consumer<T&> onJobFailed = nullptr; consumer<T&> onJobFailed = nullptr;
runnable onComplete = nullptr; runnable onComplete = nullptr;
std::atomic<int> busyWorkers = 0; std::atomic<int> busyWorkers = 0;
@ -116,7 +116,7 @@ namespace util {
ThreadPool( ThreadPool(
std::string name, std::string name,
supplier<std::shared_ptr<Worker<T, R>>> workersSupplier, supplier<std::shared_ptr<Worker<T, R>>> workersSupplier,
consumer<R&> resultConsumer, consumer<R&&> resultConsumer,
int maxWorkers=UNLIMITED int maxWorkers=UNLIMITED
) )
: logger(std::move(name)), resultConsumer(resultConsumer) { : logger(std::move(name)), resultConsumer(resultConsumer) {
@ -178,22 +178,28 @@ namespace util {
} }
void update() override { void update() override {
pullResults();
}
size_t pullResults(size_t maxResults = -1) {
if (!working) { if (!working) {
return; return 0;
} }
if (failed) { if (failed) {
throw std::runtime_error("some job failed"); throw std::runtime_error("some job failed");
} }
bool complete = false; bool complete = false;
size_t resultsProcessed = 0;
{ {
std::lock_guard<std::mutex> lock(resultsMutex); std::lock_guard<std::mutex> lock(resultsMutex);
while (!results.empty()) { while (!results.empty() && resultsProcessed < maxResults) {
ThreadPoolResult<T, R> entry = results.front(); ThreadPoolResult<T, R> entry = std::move(results.front());
results.pop(); results.pop();
++resultsProcessed;
try { try {
resultConsumer(entry.entry); resultConsumer(std::move(entry.entry));
} catch (std::exception& err) { } catch (std::exception& err) {
logger.error() << err.what(); logger.error() << err.what();
if (onJobFailed) { if (onJobFailed) {
@ -227,6 +233,7 @@ namespace util {
if (complete) { if (complete) {
terminate(); terminate();
} }
return resultsProcessed;
} }
void enqueueJob(T job) { void enqueueJob(T job) {

View file

@ -163,7 +163,7 @@ std::shared_ptr<Task> WorldConverter::startTask(
auto pool = std::make_shared<util::ThreadPool<ConvertTask, int>>( auto pool = std::make_shared<util::ThreadPool<ConvertTask, int>>(
"converter-pool", "converter-pool",
[=]() { return std::make_shared<ConverterWorker>(converter); }, [=]() { return std::make_shared<ConverterWorker>(converter); },
[=](int&) {} [=](int&&) {}
); );
auto& converterTasks = converter->tasks; auto& converterTasks = converter->tasks;
while (!converterTasks.empty()) { while (!converterTasks.empty()) {