Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/session.cpp
| Show First 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | if(!params.output_path.empty()) { | ||||
| display->reset(device, buffers->params); | display->reset(device, buffers->params); | ||||
| tonemap(params.samples); | tonemap(params.samples); | ||||
| progress.set_status("Writing Image", params.output_path); | progress.set_status("Writing Image", params.output_path); | ||||
| display->write(device, params.output_path); | display->write(device, params.output_path); | ||||
| } | } | ||||
| /* clean up */ | /* clean up */ | ||||
| foreach(RenderBuffers *buffers, tile_buffers) | foreach(RenderTile &rtile, render_tiles) | ||||
| delete buffers; | delete rtile.buffers; | ||||
| tile_manager.free_device(); | |||||
| delete buffers; | delete buffers; | ||||
| delete display; | delete display; | ||||
| delete scene; | delete scene; | ||||
| delete device; | delete device; | ||||
| TaskScheduler::exit(); | TaskScheduler::exit(); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 226 Lines • ▼ Show 20 Lines | if(params.progressive_refine == false) { | ||||
| /* for progressive refine current sample should be finished for all tiles */ | /* for progressive refine current sample should be finished for all tiles */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| thread_scoped_lock tile_lock(tile_mutex); | thread_scoped_lock tile_lock(tile_mutex); | ||||
| /* get next tile from manager */ | /* get next tile from manager */ | ||||
| Tile tile; | Tile *tile; | ||||
| int device_num = device->device_number(tile_device); | int device_num = device->device_number(tile_device); | ||||
| if(!tile_manager.next_tile(tile, device_num)) | if(!tile_manager.next_tile(tile, device_num)) | ||||
| return false; | return false; | ||||
| /* fill render tile */ | /* fill render tile */ | ||||
| rtile.x = tile_manager.state.buffer.full_x + tile.x; | rtile.x = tile_manager.state.buffer.full_x + tile->x; | ||||
| rtile.y = tile_manager.state.buffer.full_y + tile.y; | rtile.y = tile_manager.state.buffer.full_y + tile->y; | ||||
| rtile.w = tile.w; | rtile.w = tile->w; | ||||
| rtile.h = tile.h; | rtile.h = tile->h; | ||||
| rtile.start_sample = tile_manager.state.sample; | rtile.start_sample = tile_manager.state.sample; | ||||
| rtile.num_samples = tile_manager.state.num_samples; | rtile.num_samples = tile_manager.state.num_samples; | ||||
| rtile.resolution = tile_manager.state.resolution_divider; | rtile.resolution = tile_manager.state.resolution_divider; | ||||
| rtile.tile_index = tile->index; | |||||
| rtile.task = (tile->state == Tile::DENOISE)? RenderTile::DENOISE: RenderTile::PATH_TRACE; | |||||
| tile_lock.unlock(); | tile_lock.unlock(); | ||||
| /* in case of a permanent buffer, return it, otherwise we will allocate | /* in case of a permanent buffer, return it, otherwise we will allocate | ||||
| * a new temporary buffer */ | * a new temporary buffer */ | ||||
| if(!(params.background && params.output_path.empty())) { | if(!(params.background && params.output_path.empty())) { | ||||
| tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); | tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); | ||||
| rtile.buffer = buffers->buffer.device_pointer; | rtile.buffer = buffers->buffer.device_pointer; | ||||
| rtile.rng_state = buffers->rng_state.device_pointer; | rtile.rng_state = buffers->rng_state.device_pointer; | ||||
| rtile.buffers = buffers; | rtile.buffers = buffers; | ||||
| tile->buffers = buffers; | |||||
| device->map_tile(tile_device, rtile); | device->map_tile(tile_device, rtile); | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool store_rtile = false; | |||||
| if(tile->buffers == NULL) { | |||||
| /* fill buffer parameters */ | /* fill buffer parameters */ | ||||
| BufferParams buffer_params = tile_manager.params; | BufferParams buffer_params = tile_manager.params; | ||||
| buffer_params.full_x = rtile.x; | buffer_params.full_x = rtile.x; | ||||
| buffer_params.full_y = rtile.y; | buffer_params.full_y = rtile.y; | ||||
| buffer_params.width = rtile.w; | buffer_params.width = rtile.w; | ||||
| buffer_params.height = rtile.h; | buffer_params.height = rtile.h; | ||||
| buffer_params.get_offset_stride(rtile.offset, rtile.stride); | |||||
| RenderBuffers *tilebuffers; | |||||
| /* allocate buffers */ | /* allocate buffers */ | ||||
| if(params.progressive_refine) { | if(params.progressive_refine) { | ||||
| tile_lock.lock(); | tile_lock.lock(); | ||||
| if(tile_buffers.size() == 0) | if(render_tiles.size() == 0) { | ||||
| tile_buffers.resize(tile_manager.state.num_tiles, NULL); | RenderTile nulltile; | ||||
| nulltile.buffers = NULL; | |||||
| render_tiles.resize(tile_manager.state.num_tiles, nulltile); | |||||
| } | |||||
| /* In certain circumstances number of tiles in the tile manager could | /* In certain circumstances number of tiles in the tile manager could | ||||
| * be changed. This is not supported by the progressive refine feature. | * be changed. This is not supported by the progressive refine feature. | ||||
| */ | */ | ||||
| assert(tile_buffers.size() == tile_manager.state.num_tiles); | assert(render_tiles.size() == tile_manager.state.num_tiles); | ||||
| tilebuffers = tile_buffers[tile.index]; | |||||
| if(tilebuffers == NULL) { | |||||
| tilebuffers = new RenderBuffers(tile_device); | |||||
| tile_buffers[tile.index] = tilebuffers; | |||||
| tilebuffers->reset(tile_device, buffer_params); | RenderTile &stored_rtile = render_tiles[tile->index]; | ||||
| if(stored_rtile.buffers == NULL) { | |||||
| tile->buffers = new RenderBuffers(tile_device); | |||||
| tile->buffers->reset(tile_device, buffer_params); | |||||
| store_rtile = true; | |||||
| } | } | ||||
| else { | |||||
| assert(rtile.x == stored_rtile.x && | |||||
| rtile.y == stored_rtile.y && | |||||
| rtile.w == stored_rtile.w && | |||||
| rtile.h == stored_rtile.h); | |||||
| tile_lock.unlock(); | tile_lock.unlock(); | ||||
| tile->buffers = stored_rtile.buffers; | |||||
| } | |||||
| } | } | ||||
| else { | else { | ||||
| tilebuffers = new RenderBuffers(tile_device); | tile->buffers = new RenderBuffers(tile_device); | ||||
| tilebuffers->reset(tile_device, buffer_params); | tile->buffers->reset(tile_device, buffer_params); | ||||
| } | } | ||||
| } | |||||
| tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride); | |||||
| rtile.buffer = tilebuffers->buffer.device_pointer; | rtile.buffer = tile->buffers->buffer.device_pointer; | ||||
| rtile.rng_state = tilebuffers->rng_state.device_pointer; | rtile.rng_state = tile->buffers->rng_state.device_pointer; | ||||
| rtile.buffers = tilebuffers; | rtile.buffers = tile->buffers; | ||||
| rtile.sample = 0; | |||||
| if(store_rtile) { | |||||
| render_tiles[tile->index] = rtile; | |||||
| tile_lock.unlock(); | |||||
| } | |||||
| /* this will tag tile as IN PROGRESS in blender-side render pipeline, | /* this will tag tile as IN PROGRESS in blender-side render pipeline, | ||||
| * which is needed to highlight currently rendering tile before first | * which is needed to highlight currently rendering tile before first | ||||
| * sample was processed for it | * sample was processed for it | ||||
| */ | */ | ||||
| update_tile_sample(rtile); | update_tile_sample(rtile); | ||||
| return true; | return true; | ||||
| Show All 15 Lines | |||||
| } | } | ||||
| void Session::release_tile(RenderTile& rtile) | void Session::release_tile(RenderTile& rtile) | ||||
| { | { | ||||
| thread_scoped_lock tile_lock(tile_mutex); | thread_scoped_lock tile_lock(tile_mutex); | ||||
| progress.add_finished_tile(); | progress.add_finished_tile(); | ||||
| if(write_render_tile_cb) { | bool delete_tile; | ||||
| if(params.progressive_refine == false) { | |||||
| /* todo: optimize this by making it thread safe and removing lock */ | |||||
| write_render_tile_cb(rtile); | |||||
| if(tile_manager.finish_tile(rtile.tile_index, delete_tile)) { | |||||
| if(write_render_tile_cb && params.progressive_refine == false) { | |||||
| write_render_tile_cb(rtile); | |||||
| if(delete_tile) { | |||||
| delete rtile.buffers; | delete rtile.buffers; | ||||
| tile_manager.state.tiles[rtile.tile_index].buffers = NULL; | |||||
| } | |||||
| } | |||||
| } | |||||
| else { | |||||
| if(update_render_tile_cb && params.progressive_refine == false) { | |||||
| update_render_tile_cb(rtile, false); | |||||
| } | } | ||||
| } | } | ||||
| update_status_time(); | update_status_time(); | ||||
| } | } | ||||
| void Session::map_neighbor_tiles(RenderTile *tiles, Device *tile_device) | |||||
brecht: Rename to `map_neighbor_tiles` / `unmap_neighbor_tiles`? | |||||
| { | |||||
| thread_scoped_lock tile_lock(tile_mutex); | |||||
| int center_idx = tiles[4].tile_index; | |||||
| assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE); | |||||
| BufferParams buffer_params = tile_manager.params; | |||||
| int4 image_region = make_int4(buffer_params.full_x, buffer_params.full_y, | |||||
| buffer_params.full_x + buffer_params.width, buffer_params.full_y + buffer_params.height); | |||||
| for(int dy = -1, i = 0; dy <= 1; dy++) { | |||||
| for(int dx = -1; dx <= 1; dx++, i++) { | |||||
| int px = tiles[4].x + dx*params.tile_size.x; | |||||
| int py = tiles[4].y + dy*params.tile_size.y; | |||||
| if(px >= image_region.x && py >= image_region.y && | |||||
| px < image_region.z && py < image_region.w) { | |||||
| int tile_index = center_idx + dy*tile_manager.state.tile_stride + dx; | |||||
| Tile *tile = &tile_manager.state.tiles[tile_index]; | |||||
| assert(tile->buffers); | |||||
| tiles[i].buffer = tile->buffers->buffer.device_pointer; | |||||
| tiles[i].x = tile_manager.state.buffer.full_x + tile->x; | |||||
| tiles[i].y = tile_manager.state.buffer.full_y + tile->y; | |||||
| tiles[i].w = tile->w; | |||||
| tiles[i].h = tile->h; | |||||
| tiles[i].buffers = tile->buffers; | |||||
| tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride); | |||||
| } | |||||
| else { | |||||
| tiles[i].buffer = (device_ptr)NULL; | |||||
| tiles[i].buffers = NULL; | |||||
| tiles[i].x = clamp(px, image_region.x, image_region.z); | |||||
| tiles[i].y = clamp(py, image_region.y, image_region.w); | |||||
| tiles[i].w = tiles[i].h = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| assert(tiles[4].buffers); | |||||
| device->map_neighbor_tiles(tile_device, tiles); | |||||
| } | |||||
| void Session::unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device) | |||||
| { | |||||
| thread_scoped_lock tile_lock(tile_mutex); | |||||
| device->unmap_neighbor_tiles(tile_device, tiles); | |||||
| } | |||||
| void Session::run_cpu() | void Session::run_cpu() | ||||
| { | { | ||||
| bool tiles_written = false; | bool tiles_written = false; | ||||
| last_update_time = time_dt(); | last_update_time = time_dt(); | ||||
| { | { | ||||
| /* reset once to start */ | /* reset once to start */ | ||||
| ▲ Show 20 Lines • Show All 254 Lines • ▼ Show 20 Lines | void Session::reset(BufferParams& buffer_params, int samples) | ||||
| if(device_use_gl) | if(device_use_gl) | ||||
| reset_gpu(buffer_params, samples); | reset_gpu(buffer_params, samples); | ||||
| else | else | ||||
| reset_cpu(buffer_params, samples); | reset_cpu(buffer_params, samples); | ||||
| if(params.progressive_refine) { | if(params.progressive_refine) { | ||||
| thread_scoped_lock buffers_lock(buffers_mutex); | thread_scoped_lock buffers_lock(buffers_mutex); | ||||
| foreach(RenderBuffers *buffers, tile_buffers) | foreach(RenderTile &rtile, render_tiles) | ||||
| delete buffers; | delete rtile.buffers; | ||||
| tile_buffers.clear(); | render_tiles.clear(); | ||||
| } | } | ||||
| } | } | ||||
| void Session::set_samples(int samples) | void Session::set_samples(int samples) | ||||
| { | { | ||||
| if(samples != params.samples) { | if(samples != params.samples) { | ||||
| params.samples = samples; | params.samples = samples; | ||||
| tile_manager.set_samples(samples); | tile_manager.set_samples(samples); | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
| void Session::render() | void Session::render() | ||||
| { | { | ||||
| /* add path trace task */ | /* add path trace task */ | ||||
| DeviceTask task(DeviceTask::RENDER); | DeviceTask task(DeviceTask::RENDER); | ||||
| task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2); | task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2); | ||||
| task.release_tile = function_bind(&Session::release_tile, this, _1); | task.release_tile = function_bind(&Session::release_tile, this, _1); | ||||
| task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2); | |||||
| task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2); | |||||
| task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); | task.get_cancel = function_bind(&Progress::get_cancel, &this->progress); | ||||
| task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); | task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1); | ||||
| task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2); | task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2); | ||||
| task.need_finish_queue = params.progressive_refine; | task.need_finish_queue = params.progressive_refine; | ||||
| task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH; | task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH; | ||||
| task.requested_tile_size = params.tile_size; | task.requested_tile_size = params.tile_size; | ||||
| task.passes_size = tile_manager.params.get_passes_size(); | task.passes_size = tile_manager.params.get_passes_size(); | ||||
| if(params.use_denoising) { | |||||
| task.denoising_radius = params.denoising_radius; | |||||
| task.denoising_strength = params.denoising_strength; | |||||
| task.denoising_feature_strength = params.denoising_feature_strength; | |||||
| task.denoising_relative_pca = params.denoising_relative_pca; | |||||
| assert(!scene->film->need_update); | |||||
| task.pass_stride = scene->film->pass_stride; | |||||
| task.pass_denoising_data = scene->film->denoising_data_offset; | |||||
| task.pass_denoising_clean = scene->film->denoising_clean_offset; | |||||
| } | |||||
| device->task_add(task); | device->task_add(task); | ||||
| } | } | ||||
| void Session::tonemap(int sample) | void Session::tonemap(int sample) | ||||
| { | { | ||||
| /* add tonemap task */ | /* add tonemap task */ | ||||
| DeviceTask task(DeviceTask::FILM_CONVERT); | DeviceTask task(DeviceTask::FILM_CONVERT); | ||||
| Show All 27 Lines | bool Session::update_progressive_refine(bool cancel) | ||||
| if(current_time - last_update_time < params.progressive_update_timeout) { | if(current_time - last_update_time < params.progressive_update_timeout) { | ||||
| /* if last sample was processed, we need to write buffers anyway */ | /* if last sample was processed, we need to write buffers anyway */ | ||||
| if(!write && sample != 1) | if(!write && sample != 1) | ||||
| return false; | return false; | ||||
| } | } | ||||
| if(params.progressive_refine) { | if(params.progressive_refine) { | ||||
| foreach(RenderBuffers *buffers, tile_buffers) { | foreach(RenderTile &rtile, render_tiles) { | ||||
| RenderTile rtile; | |||||
| rtile.buffers = buffers; | |||||
| rtile.sample = sample; | rtile.sample = sample; | ||||
| if(write) { | if(write) { | ||||
| if(write_render_tile_cb) | if(write_render_tile_cb) | ||||
| write_render_tile_cb(rtile); | write_render_tile_cb(rtile); | ||||
| } | } | ||||
| else { | else { | ||||
| if(update_render_tile_cb) | if(update_render_tile_cb) | ||||
| update_render_tile_cb(rtile, true); | update_render_tile_cb(rtile, true); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| last_update_time = current_time; | last_update_time = current_time; | ||||
| return write; | return write; | ||||
| } | } | ||||
| void Session::device_free() | void Session::device_free() | ||||
| { | { | ||||
| scene->device_free(); | scene->device_free(); | ||||
| foreach(RenderBuffers *buffers, tile_buffers) | foreach(RenderTile &tile, render_tiles) | ||||
| delete buffers; | delete tile.buffers; | ||||
| tile_manager.free_device(); | |||||
| tile_buffers.clear(); | render_tiles.clear(); | ||||
| /* used from background render only, so no need to | /* used from background render only, so no need to | ||||
| * re-create render/display buffers here | * re-create render/display buffers here | ||||
| */ | */ | ||||
| } | } | ||||
| int Session::get_max_closure_count() | int Session::get_max_closure_count() | ||||
| { | { | ||||
| Show All 10 Lines | |||||
Rename to map_neighbor_tiles / unmap_neighbor_tiles?