Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/session.cpp
| Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | : params(params_), | ||||
| else { | else { | ||||
| buffers = new RenderBuffers(device); | buffers = new RenderBuffers(device); | ||||
| display = new DisplayBuffer(device, params.display_buffer_linear); | display = new DisplayBuffer(device, params.display_buffer_linear); | ||||
| } | } | ||||
| session_thread = NULL; | session_thread = NULL; | ||||
| scene = NULL; | scene = NULL; | ||||
| start_time = 0.0; | |||||
| reset_time = 0.0; | reset_time = 0.0; | ||||
| preview_time = 0.0; | |||||
| paused_time = 0.0; | |||||
| last_update_time = 0.0; | last_update_time = 0.0; | ||||
| delayed_reset.do_reset = false; | delayed_reset.do_reset = false; | ||||
| delayed_reset.samples = 0; | delayed_reset.samples = 0; | ||||
| display_outdated = false; | display_outdated = false; | ||||
| gpu_draw_ready = false; | gpu_draw_ready = false; | ||||
| gpu_need_tonemap = false; | gpu_need_tonemap = false; | ||||
| ▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | bool Session::draw_gpu(BufferParams& buffer_params, DeviceDrawParams& draw_params) | ||||
| return false; | return false; | ||||
| } | } | ||||
| void Session::run_gpu() | void Session::run_gpu() | ||||
| { | { | ||||
| bool tiles_written = false; | bool tiles_written = false; | ||||
| start_time = time_dt(); | |||||
| reset_time = time_dt(); | reset_time = time_dt(); | ||||
| paused_time = 0.0; | |||||
| last_update_time = time_dt(); | last_update_time = time_dt(); | ||||
| progress.set_render_start_time(start_time + paused_time); | progress.set_render_start_time(); | ||||
| while(!progress.get_cancel()) { | while(!progress.get_cancel()) { | ||||
| /* advance to next tile */ | /* advance to next tile */ | ||||
| bool no_tiles = !tile_manager.next(); | bool no_tiles = !tile_manager.next(); | ||||
| if(params.background) { | if(params.background) { | ||||
| /* if no work left and in background mode, we can stop immediately */ | /* if no work left and in background mode, we can stop immediately */ | ||||
| if(no_tiles) { | if(no_tiles) { | ||||
| Show All 10 Lines | else { | ||||
| /* reset could have happened after no_tiles was set, before this lock. | /* reset could have happened after no_tiles was set, before this lock. | ||||
| * in this case we shall not wait for pause condition | * in this case we shall not wait for pause condition | ||||
| */ | */ | ||||
| } | } | ||||
| else if(pause || no_tiles) { | else if(pause || no_tiles) { | ||||
| update_status_time(pause, no_tiles); | update_status_time(pause, no_tiles); | ||||
| while(1) { | while(1) { | ||||
| double pause_start = time_dt(); | scoped_timer pause_timer; | ||||
| pause_cond.wait(pause_lock); | pause_cond.wait(pause_lock); | ||||
| paused_time += time_dt() - pause_start; | progress.add_skip_time(pause_timer, params.background); | ||||
| if(!params.background) | |||||
| progress.set_start_time(start_time + paused_time); | |||||
| progress.set_render_start_time(start_time + paused_time); | |||||
| update_status_time(pause, no_tiles); | update_status_time(pause, no_tiles); | ||||
| progress.set_update(); | progress.set_update(); | ||||
| if(!pause) | if(!pause) | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if(progress.get_cancel()) | if(progress.get_cancel()) | ||||
| break; | break; | ||||
| } | } | ||||
| if(!no_tiles) { | if(!no_tiles) { | ||||
| /* update scene */ | /* update scene */ | ||||
| scoped_timer update_timer; | |||||
| update_scene(); | update_scene(); | ||||
| progress.add_skip_time(update_timer, params.background); | |||||
| if(!device->error_message().empty()) | if(!device->error_message().empty()) | ||||
| progress.set_error(device->error_message()); | progress.set_error(device->error_message()); | ||||
| if(progress.get_cancel()) | if(progress.get_cancel()) | ||||
| break; | break; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 251 Lines • ▼ Show 20 Lines | else { | ||||
| reset_(delayed_reset.params, delayed_reset.samples); | reset_(delayed_reset.params, delayed_reset.samples); | ||||
| delayed_reset.do_reset = false; | delayed_reset.do_reset = false; | ||||
| } | } | ||||
| else if(pause || no_tiles) { | else if(pause || no_tiles) { | ||||
| update_status_time(pause, no_tiles); | update_status_time(pause, no_tiles); | ||||
| while(1) { | while(1) { | ||||
| double pause_start = time_dt(); | scoped_timer pause_timer; | ||||
| pause_cond.wait(pause_lock); | pause_cond.wait(pause_lock); | ||||
| paused_time += time_dt() - pause_start; | progress.add_skip_time(pause_timer, params.background); | ||||
| if(!params.background) | |||||
| progress.set_start_time(start_time + paused_time); | |||||
| progress.set_render_start_time(start_time + paused_time); | |||||
| update_status_time(pause, no_tiles); | update_status_time(pause, no_tiles); | ||||
| progress.set_update(); | progress.set_update(); | ||||
| if(!pause) | if(!pause) | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if(progress.get_cancel()) | if(progress.get_cancel()) | ||||
| break; | break; | ||||
| } | } | ||||
| if(!no_tiles) { | if(!no_tiles) { | ||||
| /* buffers mutex is locked entirely while rendering each | /* buffers mutex is locked entirely while rendering each | ||||
| * sample, and released/reacquired on each iteration to allow | * sample, and released/reacquired on each iteration to allow | ||||
| * reset and draw in between */ | * reset and draw in between */ | ||||
| thread_scoped_lock buffers_lock(buffers_mutex); | thread_scoped_lock buffers_lock(buffers_mutex); | ||||
| /* update scene */ | /* update scene */ | ||||
| scoped_timer update_timer; | |||||
| update_scene(); | update_scene(); | ||||
| progress.add_skip_time(update_timer, params.background); | |||||
| if(!device->error_message().empty()) | if(!device->error_message().empty()) | ||||
| progress.set_error(device->error_message()); | progress.set_error(device->error_message()); | ||||
| if(progress.get_cancel()) | if(progress.get_cancel()) | ||||
| break; | break; | ||||
| /* update status and timing */ | /* update status and timing */ | ||||
| ▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | if(buffers) { | ||||
| if(buffer_params.modified(buffers->params)) { | if(buffer_params.modified(buffers->params)) { | ||||
| gpu_draw_ready = false; | gpu_draw_ready = false; | ||||
| buffers->reset(device, buffer_params); | buffers->reset(device, buffer_params); | ||||
| display->reset(device, buffer_params); | display->reset(device, buffer_params); | ||||
| } | } | ||||
| } | } | ||||
| tile_manager.reset(buffer_params, samples); | tile_manager.reset(buffer_params, samples); | ||||
| progress.reset_sample(); | |||||
| start_time = time_dt(); | bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX; | ||||
| preview_time = 0.0; | progress.set_total_pixel_samples(show_progress? tile_manager.state.total_pixel_samples : 0); | ||||
| paused_time = 0.0; | |||||
| if(!params.background) | if(!params.background) | ||||
| progress.set_start_time(start_time); | progress.set_start_time(); | ||||
| progress.set_render_start_time(start_time); | progress.set_render_start_time(); | ||||
| } | } | ||||
| void Session::reset(BufferParams& buffer_params, int samples) | 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); | ||||
| ▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | void Session::update_scene() | ||||
| if(scene->need_update()) { | if(scene->need_update()) { | ||||
| progress.set_status("Updating Scene"); | progress.set_status("Updating Scene"); | ||||
| MEM_GUARDED_CALL(&progress, scene->device_update, device, progress); | MEM_GUARDED_CALL(&progress, scene->device_update, device, progress); | ||||
| } | } | ||||
| } | } | ||||
| void Session::update_status_time(bool show_pause, bool show_done) | void Session::update_status_time(bool show_pause, bool show_done) | ||||
| { | { | ||||
| int sample = tile_manager.state.sample; | int progressive_sample = tile_manager.state.sample; | ||||
| int resolution = tile_manager.state.resolution_divider; | int num_samples = tile_manager.get_num_effective_samples(); | ||||
| int num_tiles = tile_manager.state.num_tiles; | |||||
| int tile = tile_manager.state.num_rendered_tiles; | int tile = tile_manager.state.num_rendered_tiles; | ||||
| int num_tiles = tile_manager.state.num_tiles; | |||||
| /* update status */ | /* update status */ | ||||
| string status, substatus; | string status, substatus; | ||||
| if(!params.progressive) { | if(!params.progressive) { | ||||
| const int progress_sample = progress.get_sample(), | |||||
| num_samples = tile_manager.get_num_effective_samples(); | |||||
| const bool is_gpu = params.device.type == DEVICE_CUDA || params.device.type == DEVICE_OPENCL; | |||||
| const bool is_multidevice = params.device.multi_devices.size() > 1; | |||||
| const bool is_cpu = params.device.type == DEVICE_CPU; | const bool is_cpu = params.device.type == DEVICE_CPU; | ||||
| const bool is_last_tile = (num_samples * num_tiles - progress_sample) < num_samples; | const bool is_last_tile = (progress.get_finished_tiles() + 1) == num_tiles; | ||||
| substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); | substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles); | ||||
| if((is_gpu && !is_multidevice && !device->info.use_split_kernel) || | if(device->show_samples() || (is_cpu && is_last_tile)) | ||||
| (is_cpu && (num_tiles == 1 || is_last_tile))) | |||||
| { | { | ||||
| /* When using split-kernel (OpenCL) each thread in a tile will be working on a different | /* Some devices automatically support showing the sample number: | ||||
| * sample. Can't display sample number when device uses split-kernel | * - CUDADevice | ||||
| */ | * - OpenCLDevice when using the megakernel (the split kernel renders multiple samples at the same time, so the current sample isn't really defined) | ||||
| * - CPUDevice when using one thread | |||||
| /* when rendering on GPU multithreading happens within single tile, as in | * For these devices, the current sample is always shown. | ||||
| * tiles are handling sequentially and in this case we could display | * | ||||
| * currently rendering sample number | * The other option is when the last tile is currently being rendered by the CPU. | ||||
| * this helps a lot from feedback point of view. | |||||
| * also display the info on CPU, when using 1 tile only | |||||
| */ | |||||
| int status_sample = progress_sample; | |||||
| if(tile > 1) { | |||||
| /* sample counter is global for all tiles, subtract samples | |||||
| * from already finished tiles to get sample counter for | |||||
| * current tile only | |||||
| */ | */ | ||||
| if(is_cpu && is_last_tile && num_tiles > 1) { | substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples); | ||||
| status_sample = num_samples - (num_samples * num_tiles - progress_sample); | |||||
| } | |||||
| else { | |||||
| status_sample -= (tile - 1) * num_samples; | |||||
| } | |||||
| } | |||||
| substatus += string_printf(", Sample %d/%d", status_sample, num_samples); | |||||
| } | } | ||||
| } | } | ||||
| else if(tile_manager.num_samples == INT_MAX) | else if(tile_manager.num_samples == INT_MAX) | ||||
| substatus = string_printf("Path Tracing Sample %d", sample+1); | substatus = string_printf("Path Tracing Sample %d", progressive_sample+1); | ||||
| else | else | ||||
| substatus = string_printf("Path Tracing Sample %d/%d", | substatus = string_printf("Path Tracing Sample %d/%d", | ||||
| sample+1, | progressive_sample+1, | ||||
| tile_manager.get_num_effective_samples()); | num_samples); | ||||
| if(show_pause) { | if(show_pause) { | ||||
| status = "Paused"; | status = "Paused"; | ||||
| } | } | ||||
| else if(show_done) { | else if(show_done) { | ||||
| status = "Done"; | status = "Done"; | ||||
| } | } | ||||
| else { | else { | ||||
| status = substatus; | status = substatus; | ||||
| substatus.clear(); | substatus.clear(); | ||||
| } | } | ||||
| progress.set_status(status, substatus); | progress.set_status(status, substatus); | ||||
| /* update timing */ | |||||
| if(preview_time == 0.0 && resolution == 1) | |||||
| preview_time = time_dt(); | |||||
| double tile_time = (tile == 0 || sample == 0)? 0.0: (time_dt() - preview_time - paused_time) / sample; | |||||
| /* negative can happen when we pause a bit before rendering, can discard that */ | |||||
| if(preview_time < 0.0) preview_time = 0.0; | |||||
| progress.set_tile(tile, tile_time); | |||||
| } | |||||
| void Session::update_progress_sample() | |||||
| { | |||||
| progress.increment_sample(); | |||||
| } | } | ||||
| void Session::path_trace() | void Session::path_trace() | ||||
| { | { | ||||
| /* add path trace task */ | /* add path trace task */ | ||||
| DeviceTask task(DeviceTask::PATH_TRACE); | DeviceTask task(DeviceTask::PATH_TRACE); | ||||
| 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.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(&Session::update_progress_sample, this); | 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; | ||||
| device->task_add(task); | device->task_add(task); | ||||
| } | } | ||||
| void Session::tonemap(int sample) | void Session::tonemap(int sample) | ||||
| ▲ Show 20 Lines • Show All 86 Lines • Show Last 20 Lines | |||||