Skip to content

Commit

Permalink
Expose checkpoint option and save/restore renders
Browse files Browse the repository at this point in the history
- Expose a checkpoint option in cli
- Create a checkpoint file after each pass if "--checkpoint" is on
- Restore from a checkpoint file if "--checkpoint" is on
- Store multi pass informations in diagnostic AOVs
- Store only last samples in depth, normal and uv AOVs
- Handle denoiser when saving and restoring a checkpoint file
	(informations are not saved in the same checkpoint file)
- Refactor diagnostic and pixel time AOVs
- Fix passes option path in cli and studio
- Clean-up tile bbox creation code snippets
- Minor changes
  • Loading branch information
oktomus committed Sep 16, 2018
1 parent 32da132 commit 691a514
Show file tree
Hide file tree
Showing 43 changed files with 2,026 additions and 1,040 deletions.
5 changes: 5 additions & 0 deletions src/appleseed.cli/commandlinehandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ CommandLineHandler::CommandLineHandler()
.set_description("display the output image"));
#endif

parser().add_option_handler(
&m_checkpoint
.add_name("--checkpoint")
.set_description("write a rendering checkpoint after each pass, or resume rendering from the last checkpoint"));

parser().add_option_handler(
&m_send_to_mplay
.add_name("--to-mplay")
Expand Down
1 change: 1 addition & 0 deletions src/appleseed.cli/commandlinehandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CommandLineHandler
#if defined __APPLE__ || defined _WIN32
foundation::FlagOptionHandler m_display_output;
#endif
foundation::FlagOptionHandler m_checkpoint;
foundation::FlagOptionHandler m_send_to_stdout;
foundation::FlagOptionHandler m_send_to_mplay;
foundation::ValueOptionHandler<int> m_send_to_hrmanpipe;
Expand Down
33 changes: 28 additions & 5 deletions src/appleseed.cli/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ namespace
if (g_cl.m_passes.is_set())
{
params.insert_path(
"generic_frame_renderer.passes",
"passes",
g_cl.m_passes.values()[0]);
}
}
Expand Down Expand Up @@ -336,6 +336,25 @@ namespace
apply_visibility_command_line_options(assembly, show_filter, hide_filter);
}

bool apply_checkpoint_command_line_option(Project& project)
{
if (g_cl.m_checkpoint.is_set())
{
if (!g_cl.m_output.is_set())
{
LOG_ERROR(g_logger, "ouput path must be specified when using checkpoints");
return false;
}

const char* file_path = g_cl.m_output.value().c_str();

set_frame_parameter(project, "checkpoint", "on");
set_frame_parameter(project, "checkpoint_path", file_path);
}

return true;
}

void apply_parameter_command_line_options(ParamArray& params)
{
for (size_t i = 0; i < g_cl.m_params.values().size(); ++i)
Expand All @@ -353,7 +372,7 @@ namespace
}
}

void apply_command_line_options(Project& project, ParamArray& params)
bool apply_command_line_options(Project& project, ParamArray& params)
{
// Apply --disable-autosave option.
if (g_cl.m_disable_autosave.is_set())
Expand Down Expand Up @@ -397,8 +416,14 @@ namespace
g_cl.m_hide_object_instances.is_set() ? g_cl.m_hide_object_instances.value() : "(?!)"); // match nothing
}

// Apply --checkpoint option.
if (!apply_checkpoint_command_line_option(project))
return false;

// Apply --parameter options.
apply_parameter_command_line_options(params);

return true;
}

#if defined __APPLE__ || defined _WIN32
Expand Down Expand Up @@ -466,9 +491,7 @@ namespace
params.merge(configuration->get_parameters());

// Apply the command line options.
apply_command_line_options(project, params);

return true;
return apply_command_line_options(project, params);
}

bool is_progressive_render(const ParamArray& params)
Expand Down
10 changes: 8 additions & 2 deletions src/appleseed/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1415,21 +1415,25 @@ set (renderer_modeling_aov_sources
renderer/modeling/aov/denoiseraov.h
renderer/modeling/aov/depthaov.cpp
renderer/modeling/aov/depthaov.h
renderer/modeling/aov/diagnosticaov.cpp
renderer/modeling/aov/diagnosticaov.h
renderer/modeling/aov/diffuseaov.cpp
renderer/modeling/aov/diffuseaov.h
renderer/modeling/aov/emissionaov.cpp
renderer/modeling/aov/emissionaov.h
renderer/modeling/aov/glossyaov.cpp
renderer/modeling/aov/glossyaov.h
renderer/modeling/aov/iaovfactory.h
renderer/modeling/aov/invalidsamplesaov.cpp
renderer/modeling/aov/invalidsamplesaov.h
renderer/modeling/aov/normalaov.cpp
renderer/modeling/aov/normalaov.h
renderer/modeling/aov/npraovs.cpp
renderer/modeling/aov/npraovs.h
renderer/modeling/aov/pixelsamplecountaov.cpp
renderer/modeling/aov/pixelsamplecountaov.h
renderer/modeling/aov/pixeltimeaov.cpp
renderer/modeling/aov/pixeltimeaov.h
renderer/modeling/aov/pixelvariationaov.cpp
renderer/modeling/aov/pixelvariationaov.h
renderer/modeling/aov/positionaov.cpp
renderer/modeling/aov/positionaov.h
renderer/modeling/aov/uvaov.cpp
Expand Down Expand Up @@ -2014,6 +2018,8 @@ set (renderer_utility_sources
renderer/utility/autodeskmax.h
renderer/utility/bbox.h
renderer/utility/dynamicspectrum.h
renderer/utility/filesystem.cpp
renderer/utility/filesystem.h
renderer/utility/iostreamop.h
renderer/utility/messagecontext.cpp
renderer/utility/messagecontext.h
Expand Down
24 changes: 16 additions & 8 deletions src/appleseed/foundation/image/genericimagefilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void GenericImageFileWriter::set_image_channels(
OIIO::ImageSpec& spec = impl->m_spec.back();

spec.nchannels = static_cast<int>(channel_count);
spec.channelnames.clear();

for (size_t i = 0; i < channel_count; i++)
{
Expand Down Expand Up @@ -195,8 +196,12 @@ void GenericImageFileWriter::set_image_spec()
}

// Channel names.
const char* channel_names[] = { "R", "G", "B", "A" };
set_image_channels(props.m_channel_count, channel_names);
// Needs to be manually set if the number of channels is higher than 4.
if (props.m_channel_count <= 4)
{
const char* channel_names[] = { "R", "G", "B", "A" };
set_image_channels(props.m_channel_count, channel_names);
}

// Format of the pixel data.
const boost::filesystem::path filepath(m_filename);
Expand Down Expand Up @@ -331,6 +336,9 @@ void GenericImageFileWriter::write_tiles(const size_t image_index)
assert(image_index < impl->m_spec.size());
const OIIO::ImageSpec& spec = impl->m_spec[image_index];

assert(spec.nchannels == spec.channelnames.size());
assert(spec.nchannels == props.m_channel_count);

// Compute the tiles' xstride offset in bytes.
size_t xstride = props.m_pixel_size;

Expand All @@ -347,7 +355,7 @@ void GenericImageFileWriter::write_tiles(const size_t image_index)
assert(tile_offset_y <= props.m_canvas_height);

// Compute the tile's ystride offset in bytes.
const size_t ystride = xstride * std::min(static_cast<size_t>(spec.width + spec.x - tile_offset_x),
const size_t ystride = xstride * std::min(static_cast<size_t>(spec.width + spec.x - tile_offset_x),
static_cast<size_t>(spec.tile_width));

// Retrieve the (tile_x, tile_y) tile.
Expand Down Expand Up @@ -421,9 +429,9 @@ void GenericImageFileWriter::write_scanlines(const size_t image_index)

// Write scanline into the file.
if (!m_writer->write_scanlines(
static_cast<int>(y_begin),
static_cast<int>(y_end),
0,
static_cast<int>(y_begin),
static_cast<int>(y_end),
0,
convert_pixel_format(props.m_pixel_format),
buffer_ptr))
{
Expand Down Expand Up @@ -469,7 +477,7 @@ void GenericImageFileWriter::write_multi_images()
const std::string msg = m_writer->geterror();
throw ExceptionIOError(msg.c_str());
}

for (size_t i = 0, e = get_image_count(); i < e; ++i)
{
if (i > 0)
Expand All @@ -484,7 +492,7 @@ void GenericImageFileWriter::write_multi_images()

write(i);
}

close_file();
}

Expand Down
113 changes: 111 additions & 2 deletions src/appleseed/foundation/image/genericprogressiveimagefilereader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ struct GenericProgressiveImageFileReader::Impl
throw ExceptionIOError(OIIO::geterror().c_str());

m_supports_random_access = m_input->supports("random_access") != 0;
read_spec(m_input->spec());
}

const OIIO::ImageSpec& spec = m_input->spec();

void read_spec(const OIIO::ImageSpec& spec)
{
m_is_tiled = spec.tile_width > 0 && spec.tile_height > 0 && spec.tile_depth > 0;

size_t tile_width, tile_height;
Expand Down Expand Up @@ -235,6 +237,17 @@ void GenericProgressiveImageFileReader::read_image_attributes(
}
}

bool GenericProgressiveImageFileReader::choose_subimage(const size_t subimage) const
{
OIIO::ImageSpec spec;
const bool success = impl->m_input->seek_subimage(subimage, 0, spec);

if (success)
impl->read_spec(spec);

return success;
}

Tile* GenericProgressiveImageFileReader::read_tile(
const size_t tile_x,
const size_t tile_y)
Expand Down Expand Up @@ -326,4 +339,100 @@ Tile* GenericProgressiveImageFileReader::read_tile(
}
}

void GenericProgressiveImageFileReader::read_tile(
const size_t tile_x,
const size_t tile_y,
Tile* output_tile)
{
assert(is_open());
assert(output_tile);
assert(output_tile->get_channel_count() == impl->m_props.m_channel_count);
assert(output_tile->get_pixel_format() == impl->m_props.m_pixel_format);

if (impl->m_is_tiled)
{
//
// Tiled image.
//
// In appleseed, for images whose width or height are not multiples
// of the tile's width or height, border tiles are actually smaller.
// In OpenImageIO, border tiles have the same size as other tiles,
// and the image's pixel data window defines which pixels of those
// tiles actually belong to the image.
//
// Since in appleseed we don't propagate pixel data windows through
// the whole image pipeline, we make sure here to return tiles of
// the correct dimensions, at some expenses.
//

const size_t origin_x = tile_x * impl->m_props.m_tile_width;
const size_t origin_y = tile_y * impl->m_props.m_tile_height;
const size_t tile_width = min(impl->m_props.m_tile_width, impl->m_props.m_canvas_width - origin_x);
const size_t tile_height = min(impl->m_props.m_tile_height, impl->m_props.m_canvas_height - origin_y);

// The tile fits perfectly into the canvas.
if (tile_width == impl->m_props.m_tile_width && tile_height == impl->m_props.m_tile_height)
{
assert(output_tile->get_width() == impl->m_props.m_tile_width);
assert(output_tile->get_height() == impl->m_props.m_tile_height);

if (!impl->m_input->read_tile(
static_cast<int>(origin_x),
static_cast<int>(origin_y),
0, // z
impl->m_input->spec().format,
output_tile->get_storage()))
throw ExceptionIOError(impl->m_input->geterror().c_str());
}
else
{
assert(output_tile->get_width() == tile_width);
assert(output_tile->get_height() == tile_height);

unique_ptr<Tile> source_tile(
new Tile(
impl->m_props.m_tile_width,
impl->m_props.m_tile_height,
impl->m_props.m_channel_count,
impl->m_props.m_pixel_format));

if (!impl->m_input->read_tile(
static_cast<int>(origin_x),
static_cast<int>(origin_y),
0, // z
impl->m_input->spec().format,
source_tile->get_storage()))
throw ExceptionIOError(impl->m_input->geterror().c_str());

for (size_t y = 0; y < tile_height; ++y)
{
memcpy(
output_tile->pixel(0, y),
source_tile->pixel(0, y),
tile_width * impl->m_props.m_pixel_size);
}
}
}
else
{
//
// Scanline image.
//

assert(output_tile->get_width() == impl->m_props.m_canvas_width);
assert(output_tile->get_height() == impl->m_props.m_canvas_height);

if (!impl->m_supports_random_access)
{
close();
impl->open();
}

if (!impl->m_input->read_image(
impl->m_input->spec().format,
output_tile->get_storage()))
throw ExceptionIOError(impl->m_input->geterror().c_str());
}
}

} // namespace foundation
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,20 @@ class APPLESEED_DLLSYMBOL GenericProgressiveImageFileReader
void read_image_attributes(
ImageAttributes& attrs) override;

// Choose the layer in the image file if available.
bool choose_subimage(const size_t subimage) const;

// Read an image tile. Returns a newly allocated tile.
Tile* read_tile(
const size_t tile_x,
const size_t tile_y) override;

// Read an image tile. Outputs the content in the given tile.
void read_tile(
const size_t tile_x,
const size_t tile_y,
Tile* output_tile);

private:
struct Impl;
Impl* impl;
Expand Down
4 changes: 3 additions & 1 deletion src/appleseed/renderer/api/aov.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@
#include "renderer/modeling/aov/aovfactoryregistrar.h"
#include "renderer/modeling/aov/aovtraits.h"
#include "renderer/modeling/aov/depthaov.h"
#include "renderer/modeling/aov/diagnosticaov.h"
#include "renderer/modeling/aov/diffuseaov.h"
#include "renderer/modeling/aov/emissionaov.h"
#include "renderer/modeling/aov/glossyaov.h"
#include "renderer/modeling/aov/iaovfactory.h"
#include "renderer/modeling/aov/invalidsamplesaov.h"
#include "renderer/modeling/aov/normalaov.h"
#include "renderer/modeling/aov/pixelsamplecountaov.h"
#include "renderer/modeling/aov/pixeltimeaov.h"
#include "renderer/modeling/aov/pixelvariationaov.h"
#include "renderer/modeling/aov/positionaov.h"
#include "renderer/modeling/aov/uvaov.h"

Expand Down
Loading

0 comments on commit 691a514

Please sign in to comment.