Report render progress if stdout is a TTY
This commit is contained in:
1 parent
d8a37c6e9a
commit
040ca57cb3
2 files changed
+86
-1
No files matched your search
+84
-1
@@ -1,8 +1,81 @@
|
|||||||
#include <fart/Engine.h>
|
#include <fart/Engine.h>
|
||||||
#include <fart/Parser.h>
|
#include <fart/Parser.h>
|
||||||
|
#include <chrono>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reports render progress to stdout when stdout is a TTY.
|
||||||
|
*
|
||||||
|
* An update is written only when progress has increased by at least 1%,
|
||||||
|
* or when progress has increased at all and at least 1 second has elapsed
|
||||||
|
* since the last update.
|
||||||
|
*/
|
||||||
|
class ProgressReporter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using clock = std::chrono::steady_clock;
|
||||||
|
|
||||||
|
explicit ProgressReporter(size_t total)
|
||||||
|
: total(total)
|
||||||
|
, enabled(total > 0u && isatty(STDOUT_FILENO))
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
last_time = clock::now();
|
||||||
|
print(0u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(size_t done)
|
||||||
|
{
|
||||||
|
if (!enabled || done <= last_done)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* (done - last_done) / total >= 1 / 100 */
|
||||||
|
bool percent_step = (done - last_done) * 100u >= total;
|
||||||
|
clock::time_point now = clock::now();
|
||||||
|
if (percent_step || (now - last_time) >= std::chrono::seconds(1))
|
||||||
|
{
|
||||||
|
last_time = now;
|
||||||
|
print(done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void finish()
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
if (last_done < total)
|
||||||
|
{
|
||||||
|
print(total);
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t total;
|
||||||
|
bool enabled;
|
||||||
|
size_t last_done = 0u;
|
||||||
|
clock::time_point last_time;
|
||||||
|
|
||||||
|
void print(size_t done)
|
||||||
|
{
|
||||||
|
last_done = done;
|
||||||
|
printf("\rRendering: %6.2f%%", (double)done * 100.0 / (double)total);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Engine::Engine(const Options & options)
|
Engine::Engine(const Options & options)
|
||||||
: options(options)
|
: options(options)
|
||||||
@@ -67,13 +140,18 @@ int Engine::run(string_view input_file, opt<string_view> output_file)
|
|||||||
options.apply_defaults();
|
options.apply_defaults();
|
||||||
|
|
||||||
Image image(*options.width, *options.height);
|
Image image(*options.width, *options.height);
|
||||||
|
ProgressReporter progress(*options.width * *options.height);
|
||||||
|
size_t pixels_done = 0u;
|
||||||
for (size_t y = 0u; y < *options.height; y++)
|
for (size_t y = 0u; y < *options.height; y++)
|
||||||
{
|
{
|
||||||
for (size_t x = 0u; x < *options.width; x++)
|
for (size_t x = 0u; x < *options.width; x++)
|
||||||
{
|
{
|
||||||
image[x, y] = *options.background;
|
image[x, y] = render_pixel(x, y);
|
||||||
|
pixels_done++;
|
||||||
|
progress.update(pixels_done);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
progress.finish();
|
||||||
|
|
||||||
if (!image_writer->write(image))
|
if (!image_writer->write(image))
|
||||||
{
|
{
|
||||||
@@ -82,3 +160,8 @@ int Engine::run(string_view input_file, opt<string_view> output_file)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color Engine::render_pixel(size_t x, size_t y)
|
||||||
|
{
|
||||||
|
return *this->options.background;
|
||||||
|
}
|
||||||
@@ -16,4 +16,6 @@ protected:
|
|||||||
Options options;
|
Options options;
|
||||||
std::unique_ptr<ImageWriter> image_writer;
|
std::unique_ptr<ImageWriter> image_writer;
|
||||||
Scene * scene = nullptr;
|
Scene * scene = nullptr;
|
||||||
|
|
||||||
|
Color render_pixel(size_t x, size_t y);
|
||||||
};
|
};
|
||||||
Reference in new issue
Block a user