Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/session/tile.cpp
| Show All 23 Lines | |||||
| #include "scene/integrator.h" | #include "scene/integrator.h" | ||||
| #include "scene/scene.h" | #include "scene/scene.h" | ||||
| #include "util/algorithm.h" | #include "util/algorithm.h" | ||||
| #include "util/foreach.h" | #include "util/foreach.h" | ||||
| #include "util/log.h" | #include "util/log.h" | ||||
| #include "util/path.h" | #include "util/path.h" | ||||
| #include "util/string.h" | #include "util/string.h" | ||||
| #include "util/system.h" | #include "util/system.h" | ||||
| #include "util/time.h" | |||||
| #include "util/types.h" | #include "util/types.h" | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* -------------------------------------------------------------------- | /* -------------------------------------------------------------------- | ||||
| * Internal functions. | * Internal functions. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 458 Lines • ▼ Show 20 Lines | |||||
| bool TileManager::write_tile(const RenderBuffers &tile_buffers) | bool TileManager::write_tile(const RenderBuffers &tile_buffers) | ||||
| { | { | ||||
| if (!write_state_.tile_out) { | if (!write_state_.tile_out) { | ||||
| if (!open_tile_output()) { | if (!open_tile_output()) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| DCHECK_EQ(tile_buffers.params.pass_stride, buffer_params_.pass_stride); | const double time_start = time_dt(); | ||||
| vector<float> pixel_storage; | DCHECK_EQ(tile_buffers.params.pass_stride, buffer_params_.pass_stride); | ||||
| const BufferParams &tile_params = tile_buffers.params; | const BufferParams &tile_params = tile_buffers.params; | ||||
| const int tile_x = tile_params.full_x - buffer_params_.full_x + tile_params.window_x; | const int tile_x = tile_params.full_x - buffer_params_.full_x + tile_params.window_x; | ||||
| const int tile_y = tile_params.full_y - buffer_params_.full_y + tile_params.window_y; | const int tile_y = tile_params.full_y - buffer_params_.full_y + tile_params.window_y; | ||||
| const int64_t pass_stride = tile_params.pass_stride; | const int64_t pass_stride = tile_params.pass_stride; | ||||
| const int64_t tile_row_stride = tile_params.width * pass_stride; | const int64_t tile_row_stride = tile_params.width * pass_stride; | ||||
| const int64_t xstride = pass_stride * sizeof(float); | vector<float> pixel_storage; | ||||
| const int64_t ystride = xstride * tile_params.width; | |||||
| const int64_t zstride = ystride * tile_params.height; | |||||
| const float *pixels = tile_buffers.buffer.data() + tile_params.window_x * pass_stride + | const float *pixels = tile_buffers.buffer.data() + tile_params.window_x * pass_stride + | ||||
| tile_params.window_y * tile_row_stride; | tile_params.window_y * tile_row_stride; | ||||
| /* If there is an overscan used for the tile copy pixels into single continuous block of memory | |||||
| * without any "gaps". | |||||
| * This is a workaround for bug in OIIO (https://github.com/OpenImageIO/oiio/pull/3176). | |||||
| * Our task reference: T93008. */ | |||||
| if (tile_params.window_x || tile_params.window_y || | |||||
| tile_params.window_width != tile_params.width || | |||||
| tile_params.window_height != tile_params.height) { | |||||
| pixel_storage.resize(pass_stride * tile_params.window_width * tile_params.window_height); | |||||
| float *pixels_continuous = pixel_storage.data(); | |||||
| const int64_t pixels_row_stride = pass_stride * tile_params.width; | |||||
| const int64_t pixels_continuous_row_stride = pass_stride * tile_params.window_width; | |||||
| for (int i = 0; i < tile_params.window_height; ++i) { | |||||
| memcpy(pixels_continuous, pixels, sizeof(float) * pixels_continuous_row_stride); | |||||
| pixels += pixels_row_stride; | |||||
| pixels_continuous += pixels_continuous_row_stride; | |||||
| } | |||||
| pixels = pixel_storage.data(); | |||||
| } | |||||
| VLOG(3) << "Write tile at " << tile_x << ", " << tile_y; | VLOG(3) << "Write tile at " << tile_x << ", " << tile_y; | ||||
| /* The image tile sizes in the OpenEXR file are different from the size of our big tiles. The | /* The image tile sizes in the OpenEXR file are different from the size of our big tiles. The | ||||
| * write_tiles() method expects a contiguous image region that will be split into tiles | * write_tiles() method expects a contiguous image region that will be split into tiles | ||||
| * internally. OpenEXR expects the size of this region to be a multiple of the tile size, | * internally. OpenEXR expects the size of this region to be a multiple of the tile size, | ||||
| * however OpenImageIO automatically adds the required padding. | * however OpenImageIO automatically adds the required padding. | ||||
| * | * | ||||
| * The only thing we have to ensure is that the tile_x and tile_y are a multiple of the | * The only thing we have to ensure is that the tile_x and tile_y are a multiple of the | ||||
| * image tile size, which happens in compute_render_tile_size. */ | * image tile size, which happens in compute_render_tile_size. */ | ||||
| const int64_t xstride = pass_stride * sizeof(float); | |||||
| const int64_t ystride = xstride * tile_params.window_width; | |||||
| const int64_t zstride = ystride * tile_params.window_height; | |||||
| if (!write_state_.tile_out->write_tiles(tile_x, | if (!write_state_.tile_out->write_tiles(tile_x, | ||||
| tile_x + tile_params.window_width, | tile_x + tile_params.window_width, | ||||
| tile_y, | tile_y, | ||||
| tile_y + tile_params.window_height, | tile_y + tile_params.window_height, | ||||
| 0, | 0, | ||||
| 1, | 1, | ||||
| TypeDesc::FLOAT, | TypeDesc::FLOAT, | ||||
| pixels, | pixels, | ||||
| xstride, | xstride, | ||||
| ystride, | ystride, | ||||
| zstride)) { | zstride)) { | ||||
| LOG(ERROR) << "Error writing tile " << write_state_.tile_out->geterror(); | LOG(ERROR) << "Error writing tile " << write_state_.tile_out->geterror(); | ||||
| return false; | return false; | ||||
| } | } | ||||
| ++write_state_.num_tiles_written; | ++write_state_.num_tiles_written; | ||||
| VLOG(3) << "Tile written in " << time_dt() - time_start << " seconds."; | |||||
| return true; | return true; | ||||
| } | } | ||||
| void TileManager::finish_write_tiles() | void TileManager::finish_write_tiles() | ||||
| { | { | ||||
| if (!write_state_.tile_out) { | if (!write_state_.tile_out) { | ||||
| /* None of the tiles were written hence the file was not created. | /* None of the tiles were written hence the file was not created. | ||||
| * Avoid creation of fully empty file since it is redundant. */ | * Avoid creation of fully empty file since it is redundant. */ | ||||
| Show All 25 Lines | void TileManager::finish_write_tiles() | ||||
| } | } | ||||
| close_tile_output(); | close_tile_output(); | ||||
| if (full_buffer_written_cb) { | if (full_buffer_written_cb) { | ||||
| full_buffer_written_cb(write_state_.filename); | full_buffer_written_cb(write_state_.filename); | ||||
| } | } | ||||
| VLOG(3) << "Tile file size is " | |||||
| << string_human_readable_number(path_file_size(write_state_.filename)) << " bytes."; | |||||
| /* Advance the counter upon explicit finish of the file. | /* Advance the counter upon explicit finish of the file. | ||||
| * Makes it possible to re-use tile manager for another scene, and avoids unnecessary increments | * Makes it possible to re-use tile manager for another scene, and avoids unnecessary increments | ||||
| * of the tile-file-within-session index. */ | * of the tile-file-within-session index. */ | ||||
| ++write_state_.tile_file_index; | ++write_state_.tile_file_index; | ||||
| write_state_.filename = ""; | write_state_.filename = ""; | ||||
| } | } | ||||
| Show All 36 Lines | |||||