From c46a6ad3bda64aff68be1850f2cb9ce1922d32ff Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 18 Dec 2025 00:30:33 +0300 Subject: [PATCH] move BlocksRenderer voxels buffer fill to main thread --- src/graphics/render/BlocksRenderer.cpp | 29 ++++------- src/graphics/render/BlocksRenderer.hpp | 20 +++++--- src/graphics/render/ChunksRenderer.cpp | 68 +++++++++++++++++++------- src/graphics/render/ChunksRenderer.hpp | 9 +++- 4 files changed, 81 insertions(+), 45 deletions(-) diff --git a/src/graphics/render/BlocksRenderer.cpp b/src/graphics/render/BlocksRenderer.cpp index 3edb40919..623ba3c3d 100644 --- a/src/graphics/render/BlocksRenderer.cpp +++ b/src/graphics/render/BlocksRenderer.cpp @@ -28,10 +28,6 @@ BlocksRenderer::BlocksRenderer( cache(cache), settings(settings) { - voxelsBuffer = std::make_unique( - CHUNK_W + voxelBufferPadding*2, - CHUNK_H, - CHUNK_D + voxelBufferPadding*2); blockDefsCache = content.getIndices()->blocks.getDefs(); } @@ -687,12 +683,9 @@ SortingMeshData BlocksRenderer::renderTranslucent( return sortingMesh; } -void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { +void BlocksRenderer::build(const Chunk* chunk, const VoxelsVolume& volume) { this->chunk = chunk; - voxelsBuffer->setPosition( - chunk->x * CHUNK_W - voxelBufferPadding, 0, - chunk->z * CHUNK_D - voxelBufferPadding); - chunks->getVoxels(*voxelsBuffer, settings.graphics.backlight.get(), chunk->top + 1); + this->voxelsBuffer = &volume; if (voxelsBuffer->pickBlockId( chunk->x * CHUNK_W, 0, chunk->z * CHUNK_D ) == BLOCK_VOID) { @@ -733,7 +726,7 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) { indexCount = 0; denseIndexCount = 0; - denseRender = false; //settings.graphics.denseRender.get(); + denseRender = false; densePass = false; render(voxels, beginEnds); @@ -762,15 +755,18 @@ ChunkMeshData BlocksRenderer::createMesh() { util::Buffer(denseIndexBuffer.get(), denseIndexCount), }, util::Buffer( - ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) + ChunkVertex::ATTRIBUTES, + sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute) ) ), std::move(sortingMesh) }; } -ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) { - build(chunk, chunks); +ChunkMesh BlocksRenderer::render( + const Chunk* chunk, const VoxelsVolume& volume +) { + build(chunk, volume); return ChunkMesh{std::make_unique>( vertexBuffer.get(), vertexCount, @@ -781,11 +777,6 @@ ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) { ), std::move(sortingMesh)}; } -VoxelsVolume* BlocksRenderer::getVoxelsBuffer() const { - return voxelsBuffer.get(); -} - size_t BlocksRenderer::getMemoryConsumption() const { - size_t volume = voxelsBuffer->getW() * voxelsBuffer->getH() * voxelsBuffer->getD(); - return capacity * (sizeof(ChunkVertex) + sizeof(uint32_t) * 2) + volume * (sizeof(voxel) + sizeof(light_t)); + return capacity * (sizeof(ChunkVertex) + sizeof(uint32_t) * 2); } diff --git a/src/graphics/render/BlocksRenderer.hpp b/src/graphics/render/BlocksRenderer.hpp index a954fad6e..2006baab3 100644 --- a/src/graphics/render/BlocksRenderer.hpp +++ b/src/graphics/render/BlocksRenderer.hpp @@ -32,13 +32,12 @@ class BlocksRenderer { size_t indexCount; size_t denseIndexCount; size_t capacity; - int voxelBufferPadding = 2; bool overflow = false; bool cancelled = false; bool densePass = false; bool denseRender = false; const Chunk* chunk = nullptr; - std::unique_ptr voxelsBuffer; + const VoxelsVolume* voxelsBuffer = nullptr; const Block* const* blockDefsCache; const ContentGfxCache& cache; @@ -152,9 +151,13 @@ class BlocksRenderer { glm::vec4 pickLight(int x, int y, int z) const; glm::vec4 pickLight(const glm::ivec3& coord) const; - glm::vec4 pickSoftLight(const glm::ivec3& coord, const glm::ivec3& right, const glm::ivec3& up) const; - glm::vec4 pickSoftLight(float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up) const; - + glm::vec4 pickSoftLight( + const glm::ivec3& coord, const glm::ivec3& right, const glm::ivec3& up + ) const; + glm::vec4 pickSoftLight( + float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up + ) const; + void render(const voxel* voxels, const int beginEnds[256][2]); SortingMeshData renderTranslucent(const voxel* voxels, int beginEnds[256][2]); public: @@ -166,10 +169,11 @@ public: ); virtual ~BlocksRenderer(); - void build(const Chunk* chunk, const Chunks* chunks); - ChunkMesh render(const Chunk* chunk, const Chunks* chunks); + void build(const Chunk* chunk, const VoxelsVolume& volume); + ChunkMesh render( + const Chunk* chunk, const VoxelsVolume& volume + ); ChunkMeshData createMesh(); - VoxelsVolume* getVoxelsBuffer() const; size_t getMemoryConsumption() const; diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index b0dfaec3e..8289967c1 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -12,24 +12,22 @@ #include "window/Camera.hpp" #include "maths/FrustumCulling.hpp" #include "util/listutil.hpp" +#include "util/ObjectsPool.hpp" #include "settings.hpp" static debug::Logger logger("chunks-render"); size_t ChunksRenderer::visibleChunks = 0; -class RendererWorker : public util::Worker, RendererResult> { - const Chunks& chunks; +class RendererWorker : public util::Worker { BlocksRenderer renderer; public: RendererWorker( const Level& level, - const Chunks& chunks, const ContentGfxCache& cache, const EngineSettings& settings ) - : chunks(chunks), - renderer( + : renderer( settings.graphics.denseRender.get() ? settings.graphics.chunkMaxVerticesDense.get() : settings.graphics.chunkMaxVertices.get(), @@ -39,8 +37,10 @@ public: ) { } - RendererResult operator()(const std::shared_ptr& chunk) override { - renderer.build(chunk.get(), &chunks); + RendererResult operator()(const RendererJob& job) override { + auto chunk = job.chunk; + auto volume = job.volume; + renderer.build(chunk.get(), *volume); if (renderer.isCancelled()) { return RendererResult { glm::ivec2(chunk->x, chunk->z), true, ChunkMeshData {}}; @@ -51,6 +51,9 @@ public: } }; +static util::ObjectsPool voxelsVolumesPool {}; +static inline const int VOXELS_BUFFER_PADDING = 2; + ChunksRenderer::ChunksRenderer( const Level* level, const Chunks& chunks, @@ -67,7 +70,7 @@ ChunksRenderer::ChunksRenderer( "chunks-render-pool", [&]() { return std::make_shared( - *level, chunks, cache, settings + *level, cache, settings ); }, [&](RendererResult& result) { @@ -87,30 +90,61 @@ ChunksRenderer::ChunksRenderer( level->content, cache, settings ); logger.info() << "created " << threadPool.getWorkersCount() << " workers"; - logger.info() << "memory consumption is " - << renderer->getMemoryConsumption() * threadPool.getWorkersCount() - << " B"; + logger.info() << "memory consumption is " + << renderer->getMemoryConsumption() * + threadPool.getWorkersCount() + + voxelsVolumesPool.countTotal() * + (sizeof(VoxelsVolume) + + (CHUNK_W + VOXELS_BUFFER_PADDING * 2) * CHUNK_H * + (CHUNK_D + VOXELS_BUFFER_PADDING * 2) * + (sizeof(voxel) + sizeof(light_t))) + << " B"; } ChunksRenderer::~ChunksRenderer() = default; +std::shared_ptr ChunksRenderer::prepareVoxelsVolume( + const Chunk& chunk +) { + auto voxelsBuffer = voxelsVolumesPool.create( + CHUNK_W + VOXELS_BUFFER_PADDING * 2, + CHUNK_H, + CHUNK_D + VOXELS_BUFFER_PADDING * 2 + ); + voxelsBuffer->setPosition( + chunk.x * CHUNK_W - VOXELS_BUFFER_PADDING, 0, + chunk.z * CHUNK_D - VOXELS_BUFFER_PADDING + ); + chunks.getVoxels( + *voxelsBuffer, settings.graphics.backlight.get(), chunk.top + 1 + ); + return voxelsBuffer; +} + const Mesh* ChunksRenderer::render( const std::shared_ptr& chunk, bool important ) { + glm::ivec2 key(chunk->x, chunk->z); chunk->flags.modified = false; if (important) { - auto mesh = renderer->render(chunk.get(), &chunks); - meshes[glm::ivec2(chunk->x, chunk->z)] = ChunkMesh { - std::move(mesh.mesh), std::move(mesh.sortingMeshData) - }; + auto voxelsBuffer = prepareVoxelsVolume(*chunk); + inwork[key] = true; + + auto mesh = renderer->render(chunk.get(), *voxelsBuffer); + meshes[glm::ivec2(chunk->x, chunk->z)] = + ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)}; return meshes[glm::ivec2(chunk->x, chunk->z)].mesh.get(); } - glm::ivec2 key(chunk->x, chunk->z); if (inwork.find(key) != inwork.end()) { return nullptr; } + auto voxelsBuffer = prepareVoxelsVolume(*chunk); inwork[key] = true; - threadPool.enqueueJob(chunk); + chunks.getVoxels( + *voxelsBuffer, settings.graphics.backlight.get(), chunk->top + 1 + ); + + threadPool.enqueueJob({chunk, std::move(voxelsBuffer)}); return nullptr; } diff --git a/src/graphics/render/ChunksRenderer.hpp b/src/graphics/render/ChunksRenderer.hpp index 9215a8638..9794a8405 100644 --- a/src/graphics/render/ChunksRenderer.hpp +++ b/src/graphics/render/ChunksRenderer.hpp @@ -21,6 +21,7 @@ class Chunks; class Frustum; class BlocksRenderer; class ContentGfxCache; +class VoxelsVolume; struct EngineSettings; struct ChunksSortEntry { @@ -38,6 +39,11 @@ struct RendererResult { ChunkMeshData meshData; }; +struct RendererJob { + std::shared_ptr chunk; + std::shared_ptr volume; +}; + class ChunksRenderer { const Chunks& chunks; const Assets& assets; @@ -48,10 +54,11 @@ class ChunksRenderer { std::unordered_map meshes; std::unordered_map inwork; std::vector indices; - util::ThreadPool, RendererResult> threadPool; + util::ThreadPool threadPool; const Mesh* retrieveChunk( size_t index, const Camera& camera, bool culling ); + std::shared_ptr prepareVoxelsVolume(const Chunk& chunk); public: ChunksRenderer( const Level* level,