From 14e03208487c8490e081e59a57713bd98c62903f Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Wed, 20 Aug 2014 15:58:37 +0200 Subject: [PATCH] Restored (partially) render progress --- src/interface/desktop/dialogrender.cpp | 12 +++---- src/interface/desktop/dialogrender.h | 7 ++-- .../software/SoftwareCanvasRenderer.cpp | 36 ++++++++++++------- src/render/software/SoftwareCanvasRenderer.h | 17 ++++----- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/interface/desktop/dialogrender.cpp b/src/interface/desktop/dialogrender.cpp index 636fd81..5c66121 100644 --- a/src/interface/desktop/dialogrender.cpp +++ b/src/interface/desktop/dialogrender.cpp @@ -116,11 +116,6 @@ DialogRender::~DialogRender() delete pixbuf_lock; } -void DialogRender::tellProgressChange(double value) -{ - emit progressChanged(value); -} - void DialogRender::tellRenderEnded() { emit renderEnded(); @@ -133,6 +128,8 @@ void DialogRender::startRender() _render_thread = new RenderThread(this, canvas_renderer); _render_thread->start(); + startTimer(100); + exec(); } @@ -179,14 +176,15 @@ void DialogRender::loadLastRender() exec(); } -void DialogRender::applyProgress(double value) +void DialogRender::timerEvent(QTimerEvent *) { double diff = difftime(time(NULL), _started); int hours = (int)floor(diff / 3600.0); int minutes = (int)floor((diff - 3600.0 * hours) / 60.0); int seconds = (int)floor(diff - 3600.0 * hours - 60.0 * minutes); _timer->setText(tr("%1:%2.%3").arg(hours).arg(minutes, 2, 10, QLatin1Char('0')).arg(seconds, 2, 10, QLatin1Char('0'))); - _progress->setValue((int)(value * 1000.0)); + + _progress->setValue((int)(canvas_renderer->getProgress() * 1000.0)); _progress->update(); } diff --git a/src/interface/desktop/dialogrender.h b/src/interface/desktop/dialogrender.h index 9206b12..57b33e3 100644 --- a/src/interface/desktop/dialogrender.h +++ b/src/interface/desktop/dialogrender.h @@ -18,25 +18,24 @@ class DialogRender : public QDialog { Q_OBJECT public: - explicit DialogRender(QWidget *parent, SoftwareCanvasRenderer* renderer); + explicit DialogRender(QWidget *parent, SoftwareCanvasRenderer *renderer); ~DialogRender(); - void tellProgressChange(double value); void tellRenderEnded(); void startRender(); void loadLastRender(); + virtual void timerEvent(QTimerEvent *event) override; + QImage* pixbuf; QMutex* pixbuf_lock; private slots: - void applyProgress(double value); void saveRender(); void applyRenderEnded(); void toneMappingChanged(); signals: - void progressChanged(double value); void renderEnded(); private: diff --git a/src/render/software/SoftwareCanvasRenderer.cpp b/src/render/software/SoftwareCanvasRenderer.cpp index 7b88187..74803ef 100644 --- a/src/render/software/SoftwareCanvasRenderer.cpp +++ b/src/render/software/SoftwareCanvasRenderer.cpp @@ -17,6 +17,7 @@ SoftwareCanvasRenderer::SoftwareCanvasRenderer() started = false; interrupted = false; canvas = new Canvas(); + progress = 0.0; rasterizers.push_back(new SkyRasterizer(this, 0)); rasterizers.push_back(new WaterRasterizer(this, 1)); @@ -55,6 +56,7 @@ void SoftwareCanvasRenderer::setSize(int width, int height, int samples) void SoftwareCanvasRenderer::render() { started = true; + progress = 0.0; render_camera->setRenderSize(canvas->getWidth(), canvas->getHeight()); @@ -63,6 +65,8 @@ void SoftwareCanvasRenderer::render() // Iterate portions int nx = canvas->getHorizontalPortionCount(); int ny = canvas->getVerticalPortionCount(); + int i = 0; + int n = nx * ny; for (int y = 0; y < ny; y++) { for (int x = 0; x < nx; x++) @@ -71,16 +75,20 @@ void SoftwareCanvasRenderer::render() if (not interrupted) { + progress_segment = 0.2 / (double)n; portion->preparePixels(); - rasterize(portion, true); + rasterize(portion); } if (not interrupted) { - applyPixelShader(portion, true); + progress_segment = 0.8 / (double)n; + applyPixelShader(portion); } portion->discardPixels(); + i++; + progress = (double)i / (double)n; } } } @@ -93,31 +101,27 @@ void SoftwareCanvasRenderer::interrupt() { current_work->interrupt(); } - for (auto &rasterizer:getRasterizers()) + for (auto &rasterizer:rasterizers) { rasterizer->interrupt(); } } -const std::vector &SoftwareCanvasRenderer::getRasterizers() const -{ - return rasterizers; -} - const Rasterizer &SoftwareCanvasRenderer::getRasterizer(int client_id) const { - return *(getRasterizers()[client_id]); + return *(rasterizers[client_id]); } -void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded) +void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion) { - for (auto &rasterizer:getRasterizers()) + for (auto &rasterizer:rasterizers) { rasterizer->rasterizeToCanvas(portion); + progress += progress_segment / (double)rasterizers.size(); } } -void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threaded) +void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion) { // Subdivide in chunks int chunk_size = 64; @@ -125,6 +129,13 @@ void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threa int chunks_y = (portion->getHeight() - 1) / chunk_size + 1; int units = chunks_x * chunks_y; + // Estimate chunks + int n = 0; + for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2) + { + n += chunk_size / sub_chunk_size; + } + // Render chunks in parallel for (int sub_chunk_size = chunk_size; sub_chunk_size >= 1; sub_chunk_size /= 2) { @@ -139,5 +150,6 @@ void SoftwareCanvasRenderer::applyPixelShader(CanvasPortion *portion, bool threa current_work = &work; work.perform(); current_work = NULL; + progress += progress_segment * (double)(chunk_size / sub_chunk_size) / (double)n; } } diff --git a/src/render/software/SoftwareCanvasRenderer.h b/src/render/software/SoftwareCanvasRenderer.h index 58195f3..a40d69a 100644 --- a/src/render/software/SoftwareCanvasRenderer.h +++ b/src/render/software/SoftwareCanvasRenderer.h @@ -23,6 +23,7 @@ public: virtual ~SoftwareCanvasRenderer(); inline const Canvas *getCanvas() const {return canvas;} + inline double getProgress() const {return progress;} /** * Set the renderer configuration. @@ -46,11 +47,6 @@ public: */ void interrupt(); - /** - * @brief Get the list of objects that can be rasterized to polygons on a canvas. - */ - virtual const std::vector &getRasterizers() const; - /** * Get a rasterizer by its client id. */ @@ -59,19 +55,18 @@ public: protected: /** * @brief Rasterize the scenery into a canvas portion. - * - * If 'threaded' is true, the rasterization will take advantage of multiple CPU cores. */ - void rasterize(CanvasPortion *portion, bool threaded=false); + void rasterize(CanvasPortion *portion); /** * @brief Apply pixel shader to fragments stored in the CanvasPortion. - * - * If 'threaded' is true, the shader will take advantage of multiple CPU cores. */ - void applyPixelShader(CanvasPortion *portion, bool threaded=true); + void applyPixelShader(CanvasPortion *portion); private: + double progress; + double progress_segment; + Canvas *canvas; std::vector rasterizers; bool started;