Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/session.cpp
| Show First 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| cancel(); | cancel(); | ||||
| if (buffers && params.write_render_cb) { | if (buffers && params.write_render_cb) { | ||||
| /* Copy to display buffer and write out image if requested */ | /* Copy to display buffer and write out image if requested */ | ||||
| delete display; | delete display; | ||||
| display = new DisplayBuffer(device, false); | display = new DisplayBuffer(device, false); | ||||
| display->reset(buffers->params); | display->reset(buffers->get_params()); | ||||
| copy_to_display_buffer(params.samples); | copy_to_display_buffer(params.samples); | ||||
| int w = display->draw_width; | int w = display->get_draw_width(); | ||||
| int h = display->draw_height; | int h = display->get_draw_height(); | ||||
| uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h); | uchar4 *pixels = display->get_rgba_byte().copy_from_device(0, w, h); | ||||
| params.write_render_cb((uchar *)pixels, w, h, 4); | params.write_render_cb((uchar *)pixels, w, h, 4); | ||||
| } | } | ||||
| /* clean up */ | /* clean up */ | ||||
| tile_manager.device_free(); | tile_manager.device_free(); | ||||
| delete buffers; | delete buffers; | ||||
| delete display; | delete display; | ||||
| ▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| /* block for buffer access */ | /* block for buffer access */ | ||||
| thread_scoped_lock display_lock(display_mutex); | thread_scoped_lock display_lock(display_mutex); | ||||
| /* first check we already rendered something */ | /* first check we already rendered something */ | ||||
| if (gpu_draw_ready) { | if (gpu_draw_ready) { | ||||
| /* then verify the buffers have the expected size, so we don't | /* then verify the buffers have the expected size, so we don't | ||||
| * draw previous results in a resized window */ | * draw previous results in a resized window */ | ||||
| if (buffer_params.width == display->params.width && | if (buffer_params.get_width() == display->get_params().get_width() && | ||||
| buffer_params.height == display->params.height) { | buffer_params.get_height() == display->get_params().get_height()) { | ||||
| /* for CUDA we need to do tone-mapping still, since we can | /* for CUDA we need to do tone-mapping still, since we can | ||||
| * only access GL buffers from the main thread. */ | * only access GL buffers from the main thread. */ | ||||
| if (gpu_need_display_buffer_update) { | if (gpu_need_display_buffer_update) { | ||||
| thread_scoped_lock buffers_lock(buffers_mutex); | thread_scoped_lock buffers_lock(buffers_mutex); | ||||
| copy_to_display_buffer(tile_manager.state.sample); | copy_to_display_buffer(tile_manager.state.sample); | ||||
| gpu_need_display_buffer_update = false; | gpu_need_display_buffer_update = false; | ||||
| gpu_need_display_buffer_update_cond.notify_all(); | gpu_need_display_buffer_update_cond.notify_all(); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | else { | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| break; | break; | ||||
| } | } | ||||
| if (!no_tiles) { | if (!no_tiles) { | ||||
| /* update scene */ | /* update scene */ | ||||
| scoped_timer update_timer; | scoped_timer update_timer; | ||||
| if (update_scene()) { | if (update_scene()) { | ||||
| profiler.reset(scene->shaders.size(), scene->objects.size()); | profiler.reset(scene->get_shaders().size(), scene->get_objects().size()); | ||||
| } | } | ||||
| progress.add_skip_time(update_timer, params.background); | 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 68 Lines • ▼ Show 20 Lines | |||||
| bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_params) | bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_params) | ||||
| { | { | ||||
| thread_scoped_lock display_lock(display_mutex); | thread_scoped_lock display_lock(display_mutex); | ||||
| /* first check we already rendered something */ | /* first check we already rendered something */ | ||||
| if (display->draw_ready()) { | if (display->draw_ready()) { | ||||
| /* then verify the buffers have the expected size, so we don't | /* then verify the buffers have the expected size, so we don't | ||||
| * draw previous results in a resized window */ | * draw previous results in a resized window */ | ||||
| if (buffer_params.width == display->params.width && | if (buffer_params.get_width() == display->get_params().get_width() && | ||||
| buffer_params.height == display->params.height) { | buffer_params.get_height() == display->get_params().get_height()) { | ||||
| display->draw(device, draw_params); | display->draw(device, draw_params); | ||||
| if (display_outdated && (time_dt() - reset_time) > params.text_timeout) | if (display_outdated && (time_dt() - reset_time) > params.text_timeout) | ||||
| return false; | return false; | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| Show All 30 Lines | bool Session::steal_tile(RenderTile &rtile, Device *tile_device, thread_scoped_lock &tile_lock) | ||||
| /* If the last stealable tile finished on its own, give up. */ | /* If the last stealable tile finished on its own, give up. */ | ||||
| if (tile_stealing_state != GOT_TILE) { | if (tile_stealing_state != GOT_TILE) { | ||||
| tile_stealing_state = NOT_STEALING; | tile_stealing_state = NOT_STEALING; | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Successfully stole a tile, now move it to the new device. */ | /* Successfully stole a tile, now move it to the new device. */ | ||||
| rtile = stolen_tile; | rtile = stolen_tile; | ||||
| rtile.buffers->buffer.move_device(tile_device); | rtile.get_buffers()->get_buffer().move_device(tile_device); | ||||
| rtile.buffer = rtile.buffers->buffer.device_pointer; | rtile.set_buffer(rtile.get_buffers()->get_buffer().device_pointer); | ||||
| rtile.stealing_state = RenderTile::NO_STEALING; | rtile.set_stealing_state(RenderTile::NO_STEALING); | ||||
| rtile.num_samples -= (rtile.sample - rtile.start_sample); | rtile.get_num_samples() -= (rtile.get_sample() - rtile.get_start_sample()); | ||||
| rtile.start_sample = rtile.sample; | rtile.set_start_sample(rtile.get_sample()); | ||||
| tile_stealing_state = NOT_STEALING; | tile_stealing_state = NOT_STEALING; | ||||
| /* Poke any threads which might be waiting for NOT_STEALING above. */ | /* Poke any threads which might be waiting for NOT_STEALING above. */ | ||||
| tile_steal_cond.notify_one(); | tile_steal_cond.notify_one(); | ||||
| return true; | return true; | ||||
| } | } | ||||
| Show All 27 Lines | if ((tile_types & RenderTile::DENOISE) && !progress.get_cancel() && tile_manager.has_tiles()) { | ||||
| denoising_cond.wait(tile_lock); | denoising_cond.wait(tile_lock); | ||||
| continue; | continue; | ||||
| } | } | ||||
| return steal_tile(rtile, tile_device, tile_lock); | return steal_tile(rtile, tile_device, tile_lock); | ||||
| } | } | ||||
| /* fill render tile */ | /* fill render tile */ | ||||
| rtile.x = tile_manager.state.buffer.full_x + tile->x; | rtile.set_x(tile_manager.state.buffer.get_full_x() + tile->x); | ||||
| rtile.y = tile_manager.state.buffer.full_y + tile->y; | rtile.set_y(tile_manager.state.buffer.get_full_y() + tile->y); | ||||
| rtile.w = tile->w; | rtile.set_w(tile->w); | ||||
| rtile.h = tile->h; | rtile.set_h(tile->h); | ||||
| rtile.start_sample = tile_manager.state.sample; | rtile.set_start_sample(tile_manager.state.sample); | ||||
| rtile.num_samples = tile_manager.state.num_samples; | rtile.set_num_samples(tile_manager.state.num_samples); | ||||
| rtile.resolution = tile_manager.state.resolution_divider; | rtile.set_resolution(tile_manager.state.resolution_divider); | ||||
| rtile.tile_index = tile->index; | rtile.set_tile_index(tile->index); | ||||
| if (tile->state == Tile::DENOISE) { | if (tile->state == Tile::DENOISE) { | ||||
| rtile.task = RenderTile::DENOISE; | rtile.set_task(RenderTile::DENOISE); | ||||
| } | } | ||||
| else { | else { | ||||
| if (tile_device->info.type == DEVICE_CPU) { | if (tile_device->info.type == DEVICE_CPU) { | ||||
| stealable_tiles++; | stealable_tiles++; | ||||
| rtile.stealing_state = RenderTile::CAN_BE_STOLEN; | rtile.set_stealing_state(RenderTile::CAN_BE_STOLEN); | ||||
| } | } | ||||
| if (read_bake_tile_cb) { | if (read_bake_tile_cb) { | ||||
| rtile.task = RenderTile::BAKE; | rtile.set_task(RenderTile::BAKE); | ||||
| } | } | ||||
| else { | else { | ||||
| rtile.task = RenderTile::PATH_TRACE; | rtile.set_task(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 (buffers) { | if (buffers) { | ||||
| tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); | tile_manager.state.buffer.get_offset_stride(rtile.get_offset(), rtile.get_stride()); | ||||
| rtile.buffer = buffers->buffer.device_pointer; | rtile.set_buffer(buffers->get_buffer().device_pointer); | ||||
| rtile.buffers = buffers; | rtile.set_buffers(buffers); | ||||
| device->map_tile(tile_device, rtile); | device->map_tile(tile_device, rtile); | ||||
| /* Reset copy state, since buffer contents change after the tile was acquired */ | /* Reset copy state, since buffer contents change after the tile was acquired */ | ||||
| buffers->map_neighbor_copied = false; | buffers->set_map_neighbor_copied(false); | ||||
| /* This hack ensures that the copy in 'MultiDevice::map_neighbor_tiles' accounts | /* This hack ensures that the copy in 'MultiDevice::map_neighbor_tiles' accounts | ||||
| * for the buffer resolution divider. */ | * for the buffer resolution divider. */ | ||||
| buffers->buffer.data_width = (buffers->params.width * buffers->params.get_passes_size()) / | buffers->get_buffer().data_width = (buffers->get_params().get_width() * | ||||
| buffers->get_params().get_passes_size()) / | |||||
| tile_manager.state.resolution_divider; | |||||
| buffers->get_buffer().data_height = buffers->get_params().get_height() / | |||||
| tile_manager.state.resolution_divider; | tile_manager.state.resolution_divider; | ||||
| buffers->buffer.data_height = buffers->params.height / tile_manager.state.resolution_divider; | |||||
| return true; | return true; | ||||
| } | } | ||||
| if (tile->buffers == NULL) { | 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.set_full_x(rtile.get_x()); | ||||
| buffer_params.full_y = rtile.y; | buffer_params.set_full_y(rtile.get_y()); | ||||
| buffer_params.width = rtile.w; | buffer_params.set_width(rtile.get_w()); | ||||
| buffer_params.height = rtile.h; | buffer_params.set_height(rtile.get_h()); | ||||
| /* allocate buffers */ | /* allocate buffers */ | ||||
| tile->buffers = new RenderBuffers(tile_device); | tile->buffers = new RenderBuffers(tile_device); | ||||
| tile->buffers->reset(buffer_params); | tile->buffers->reset(buffer_params); | ||||
| } | } | ||||
| tile->buffers->map_neighbor_copied = false; | tile->buffers->set_map_neighbor_copied(false); | ||||
| tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride); | tile->buffers->get_params().get_offset_stride(rtile.get_offset(), rtile.get_stride()); | ||||
| rtile.buffer = tile->buffers->buffer.device_pointer; | rtile.set_buffer(tile->buffers->get_buffer().device_pointer); | ||||
| rtile.buffers = tile->buffers; | rtile.set_buffers(tile->buffers); | ||||
| rtile.sample = tile_manager.state.sample; | rtile.set_sample(tile_manager.state.sample); | ||||
| if (read_bake_tile_cb) { | if (read_bake_tile_cb) { | ||||
| /* This will read any passes needed as input for baking. */ | /* This will read any passes needed as input for baking. */ | ||||
| { | { | ||||
| thread_scoped_lock tile_lock(tile_mutex); | thread_scoped_lock tile_lock(tile_mutex); | ||||
| read_bake_tile_cb(rtile); | read_bake_tile_cb(rtile); | ||||
| } | } | ||||
| rtile.buffers->buffer.copy_to_device(); | rtile.get_buffers()->get_buffer().copy_to_device(); | ||||
| } | } | ||||
| else { | else { | ||||
| /* 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); | ||||
| } | } | ||||
| Show All 14 Lines | void Session::update_tile_sample(RenderTile &rtile) | ||||
| update_status_time(); | update_status_time(); | ||||
| } | } | ||||
| void Session::release_tile(RenderTile &rtile, const bool need_denoise) | void Session::release_tile(RenderTile &rtile, const bool need_denoise) | ||||
| { | { | ||||
| thread_scoped_lock tile_lock(tile_mutex); | thread_scoped_lock tile_lock(tile_mutex); | ||||
| if (rtile.stealing_state != RenderTile::NO_STEALING) { | if (rtile.get_stealing_state() != RenderTile::NO_STEALING) { | ||||
| stealable_tiles--; | stealable_tiles--; | ||||
| if (rtile.stealing_state == RenderTile::WAS_STOLEN) { | if (rtile.get_stealing_state() == RenderTile::WAS_STOLEN) { | ||||
| /* If the tile is being stolen, don't release it here - the new device will pick up where | /* If the tile is being stolen, don't release it here - the new device will pick up where | ||||
| * the old one left off. */ | * the old one left off. */ | ||||
| assert(tile_stealing_state == RELEASING_TILE); | assert(tile_stealing_state == RELEASING_TILE); | ||||
| assert(rtile.sample < rtile.start_sample + rtile.num_samples); | assert(rtile.get_sample() < rtile.get_start_sample() + rtile.get_num_samples()); | ||||
| tile_stealing_state = GOT_TILE; | tile_stealing_state = GOT_TILE; | ||||
| stolen_tile = rtile; | stolen_tile = rtile; | ||||
| tile_steal_cond.notify_all(); | tile_steal_cond.notify_all(); | ||||
| return; | return; | ||||
| } | } | ||||
| else if (stealable_tiles == 0) { | else if (stealable_tiles == 0) { | ||||
| /* If this was the last stealable tile, wake up any threads still waiting for one. */ | /* If this was the last stealable tile, wake up any threads still waiting for one. */ | ||||
| tile_steal_cond.notify_all(); | tile_steal_cond.notify_all(); | ||||
| } | } | ||||
| } | } | ||||
| progress.add_finished_tile(rtile.task == RenderTile::DENOISE); | progress.add_finished_tile(rtile.get_task() == RenderTile::DENOISE); | ||||
| bool delete_tile; | bool delete_tile; | ||||
| if (tile_manager.finish_tile(rtile.tile_index, need_denoise, delete_tile)) { | if (tile_manager.finish_tile(rtile.get_tile_index(), need_denoise, delete_tile)) { | ||||
| /* Finished tile pixels write. */ | /* Finished tile pixels write. */ | ||||
| if (write_render_tile_cb && params.progressive_refine == false) { | if (write_render_tile_cb && params.progressive_refine == false) { | ||||
| write_render_tile_cb(rtile); | write_render_tile_cb(rtile); | ||||
| } | } | ||||
| if (delete_tile) { | if (delete_tile) { | ||||
| delete rtile.buffers; | delete rtile.get_buffers(); | ||||
| tile_manager.state.tiles[rtile.tile_index].buffers = NULL; | tile_manager.state.tiles[rtile.get_tile_index()].buffers = NULL; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* In progress tile pixels update. */ | /* In progress tile pixels update. */ | ||||
| if (update_render_tile_cb && params.progressive_refine == false) { | if (update_render_tile_cb && params.progressive_refine == false) { | ||||
| update_render_tile_cb(rtile, false); | update_render_tile_cb(rtile, false); | ||||
| } | } | ||||
| } | } | ||||
| update_status_time(); | update_status_time(); | ||||
| /* Notify denoising thread that a tile was finished. */ | /* Notify denoising thread that a tile was finished. */ | ||||
| denoising_cond.notify_all(); | denoising_cond.notify_all(); | ||||
| } | } | ||||
| void Session::map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device) | void Session::map_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device) | ||||
| { | { | ||||
| thread_scoped_lock tile_lock(tile_mutex); | thread_scoped_lock tile_lock(tile_mutex); | ||||
| const int4 image_region = make_int4( | const int4 image_region = make_int4( | ||||
| tile_manager.state.buffer.full_x, | tile_manager.state.buffer.get_full_x(), | ||||
| tile_manager.state.buffer.full_y, | tile_manager.state.buffer.get_full_y(), | ||||
| tile_manager.state.buffer.full_x + tile_manager.state.buffer.width, | tile_manager.state.buffer.get_full_x() + tile_manager.state.buffer.get_width(), | ||||
| tile_manager.state.buffer.full_y + tile_manager.state.buffer.height); | tile_manager.state.buffer.get_full_y() + tile_manager.state.buffer.get_height()); | ||||
| RenderTile ¢er_tile = neighbors.tiles[RenderTileNeighbors::CENTER]; | RenderTile ¢er_tile = neighbors.get_tiles()[RenderTileNeighbors::CENTER]; | ||||
| if (!tile_manager.schedule_denoising) { | if (!tile_manager.schedule_denoising) { | ||||
| /* Fix up tile slices with overlap. */ | /* Fix up tile slices with overlap. */ | ||||
| if (tile_manager.slice_overlap != 0) { | if (tile_manager.slice_overlap != 0) { | ||||
| int y = max(center_tile.y - tile_manager.slice_overlap, image_region.y); | int y = max(center_tile.get_y() - tile_manager.slice_overlap, image_region.y); | ||||
| center_tile.h = min(center_tile.y + center_tile.h + tile_manager.slice_overlap, | int h = min(center_tile.get_y() + center_tile.get_h() + tile_manager.slice_overlap, | ||||
| image_region.w) - | image_region.w) - | ||||
| y; | y; | ||||
| center_tile.y = y; | |||||
| center_tile.set_h(h); | |||||
| center_tile.set_y(y); | |||||
| } | } | ||||
| /* Tiles are not being denoised individually, which means the entire image is processed. */ | /* Tiles are not being denoised individually, which means the entire image is processed. */ | ||||
| neighbors.set_bounds_from_center(); | neighbors.set_bounds_from_center(); | ||||
| } | } | ||||
| else { | else { | ||||
| int center_idx = center_tile.tile_index; | int center_idx = center_tile.get_tile_index(); | ||||
| assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE); | assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE); | ||||
| for (int dy = -1, i = 0; dy <= 1; dy++) { | for (int dy = -1, i = 0; dy <= 1; dy++) { | ||||
| for (int dx = -1; dx <= 1; dx++, i++) { | for (int dx = -1; dx <= 1; dx++, i++) { | ||||
| RenderTile &rtile = neighbors.tiles[i]; | RenderTile &rtile = neighbors.get_tiles()[i]; | ||||
| int nindex = tile_manager.get_neighbor_index(center_idx, i); | int nindex = tile_manager.get_neighbor_index(center_idx, i); | ||||
| if (nindex >= 0) { | if (nindex >= 0) { | ||||
| Tile *tile = &tile_manager.state.tiles[nindex]; | Tile *tile = &tile_manager.state.tiles[nindex]; | ||||
| rtile.x = image_region.x + tile->x; | rtile.set_x(image_region.x + tile->x); | ||||
| rtile.y = image_region.y + tile->y; | rtile.set_y(image_region.y + tile->y); | ||||
| rtile.w = tile->w; | rtile.set_w(tile->w); | ||||
| rtile.h = tile->h; | rtile.set_h(tile->h); | ||||
| if (buffers) { | if (buffers) { | ||||
| tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride); | tile_manager.state.buffer.get_offset_stride(rtile.get_offset(), rtile.get_stride()); | ||||
| rtile.buffer = buffers->buffer.device_pointer; | rtile.set_buffer(buffers->get_buffer().device_pointer); | ||||
| rtile.buffers = buffers; | rtile.set_buffers(buffers); | ||||
| } | } | ||||
| else { | else { | ||||
| assert(tile->buffers); | assert(tile->buffers); | ||||
| tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride); | tile->buffers->get_params().get_offset_stride(rtile.get_offset(), rtile.get_stride()); | ||||
| rtile.buffer = tile->buffers->buffer.device_pointer; | rtile.set_buffer(tile->buffers->get_buffer().device_pointer); | ||||
| rtile.buffers = tile->buffers; | rtile.set_buffers(tile->buffers); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| int px = center_tile.x + dx * params.tile_size.x; | int px = center_tile.get_x() + dx * params.tile_size.x; | ||||
| int py = center_tile.y + dy * params.tile_size.y; | int py = center_tile.get_y() + dy * params.tile_size.y; | ||||
| rtile.x = clamp(px, image_region.x, image_region.z); | rtile.set_x(clamp(px, image_region.x, image_region.z)); | ||||
| rtile.y = clamp(py, image_region.y, image_region.w); | rtile.set_y(clamp(py, image_region.y, image_region.w)); | ||||
| rtile.w = rtile.h = 0; | rtile.set_h(0); | ||||
| rtile.set_w(0); | |||||
| rtile.buffer = (device_ptr)NULL; | rtile.set_buffer((device_ptr)NULL); | ||||
| rtile.buffers = NULL; | rtile.set_buffers(NULL); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| assert(center_tile.buffers); | assert(center_tile.get_buffers()); | ||||
| device->map_neighbor_tiles(tile_device, neighbors); | device->map_neighbor_tiles(tile_device, neighbors); | ||||
| /* The denoised result is written back to the original tile. */ | /* The denoised result is written back to the original tile. */ | ||||
| neighbors.target = center_tile; | neighbors.set_target(center_tile); | ||||
| } | } | ||||
| void Session::unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device) | void Session::unmap_neighbor_tiles(RenderTileNeighbors &neighbors, Device *tile_device) | ||||
| { | { | ||||
| thread_scoped_lock tile_lock(tile_mutex); | thread_scoped_lock tile_lock(tile_mutex); | ||||
| device->unmap_neighbor_tiles(tile_device, neighbors); | device->unmap_neighbor_tiles(tile_device, neighbors); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | else { | ||||
| if (progress.get_cancel()) | if (progress.get_cancel()) | ||||
| break; | break; | ||||
| } | } | ||||
| if (!no_tiles) { | if (!no_tiles) { | ||||
| /* update scene */ | /* update scene */ | ||||
| scoped_timer update_timer; | scoped_timer update_timer; | ||||
| if (update_scene()) { | if (update_scene()) { | ||||
| profiler.reset(scene->shaders.size(), scene->objects.size()); | profiler.reset(scene->get_shaders().size(), scene->get_objects().size()); | ||||
| } | } | ||||
| progress.add_skip_time(update_timer, params.background); | 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 194 Lines • ▼ Show 20 Lines | if (session_thread) { | ||||
| delete session_thread; | delete session_thread; | ||||
| } | } | ||||
| session_thread = NULL; | session_thread = NULL; | ||||
| } | } | ||||
| bool Session::update_scene() | bool Session::update_scene() | ||||
| { | { | ||||
| thread_scoped_lock scene_lock(scene->mutex); | thread_scoped_lock scene_lock(scene->get_mutex()); | ||||
| /* update camera if dimensions changed for progressive render. the camera | /* update camera if dimensions changed for progressive render. the camera | ||||
| * knows nothing about progressive or cropped rendering, it just gets the | * knows nothing about progressive or cropped rendering, it just gets the | ||||
| * image dimensions passed in */ | * image dimensions passed in */ | ||||
| Camera *cam = scene->camera; | Camera *cam = scene->get_camera(); | ||||
| int width = tile_manager.state.buffer.full_width; | int width = tile_manager.state.buffer.get_full_width(); | ||||
| int height = tile_manager.state.buffer.full_height; | int height = tile_manager.state.buffer.get_full_height(); | ||||
| int resolution = tile_manager.state.resolution_divider; | int resolution = tile_manager.state.resolution_divider; | ||||
| cam->set_screen_size_and_resolution(width, height, resolution); | cam->set_screen_size_and_resolution(width, height, resolution); | ||||
| /* number of samples is needed by multi jittered | /* number of samples is needed by multi jittered | ||||
| * sampling pattern and by baking */ | * sampling pattern and by baking */ | ||||
| Integrator *integrator = scene->integrator; | Integrator *integrator = scene->get_integrator(); | ||||
| BakeManager *bake_manager = scene->bake_manager; | BakeManager *bake_manager = scene->get_bake_manager(); | ||||
| if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) { | if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) { | ||||
| int aa_samples = tile_manager.num_samples; | int aa_samples = tile_manager.num_samples; | ||||
| integrator->set_aa_samples(aa_samples); | integrator->set_aa_samples(aa_samples); | ||||
| if (integrator->is_modified()) { | if (integrator->is_modified()) { | ||||
| integrator->tag_update(scene); | integrator->tag_update(scene); | ||||
| ▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | bool Session::render_need_denoise(bool &delayed) | ||||
| if (params.background) { | if (params.background) { | ||||
| /* Background render, only denoise when rendering the last sample. */ | /* Background render, only denoise when rendering the last sample. */ | ||||
| return tile_manager.done(); | return tile_manager.done(); | ||||
| } | } | ||||
| /* Viewport render. */ | /* Viewport render. */ | ||||
| /* It can happen that denoising was already enabled, but the scene still needs an update. */ | /* It can happen that denoising was already enabled, but the scene still needs an update. */ | ||||
| if (scene->film->is_modified() || !scene->film->get_denoising_data_offset()) { | if (scene->get_film()->is_modified() || !scene->get_film()->get_denoising_data_offset()) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* Immediately denoise when we reach the start sample or last sample. */ | /* Immediately denoise when we reach the start sample or last sample. */ | ||||
| const int num_samples_finished = tile_manager.state.sample + 1; | const int num_samples_finished = tile_manager.state.sample + 1; | ||||
| if (num_samples_finished == params.denoising.start_sample || | if (num_samples_finished == params.denoising.start_sample || | ||||
| num_samples_finished == params.samples) { | num_samples_finished == params.samples) { | ||||
| return true; | return true; | ||||
| Show All 12 Lines | |||||
| void Session::render(bool need_denoise) | void Session::render(bool need_denoise) | ||||
| { | { | ||||
| if (buffers && tile_manager.state.sample == tile_manager.range_start_sample) { | if (buffers && tile_manager.state.sample == tile_manager.range_start_sample) { | ||||
| /* Clear buffers. */ | /* Clear buffers. */ | ||||
| buffers->zero(); | buffers->zero(); | ||||
| } | } | ||||
| if (tile_manager.state.buffer.width == 0 || tile_manager.state.buffer.height == 0) { | if (tile_manager.state.buffer.get_width() == 0 || tile_manager.state.buffer.get_height() == 0) { | ||||
| return; /* Avoid empty launches. */ | return; /* Avoid empty launches. */ | ||||
| } | } | ||||
| /* 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, _2, _1, _3); | task.acquire_tile = function_bind(&Session::acquire_tile, this, _2, _1, _3); | ||||
| task.release_tile = function_bind(&Session::release_tile, this, _1, need_denoise); | task.release_tile = function_bind(&Session::release_tile, this, _1, need_denoise); | ||||
| task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2); | 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.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.get_tile_stolen = function_bind(&Session::get_tile_stolen, this); | task.get_tile_stolen = function_bind(&Session::get_tile_stolen, this); | ||||
| task.need_finish_queue = params.progressive_refine; | task.need_finish_queue = params.progressive_refine; | ||||
| task.integrator_branched = scene->integrator->get_method() == Integrator::BRANCHED_PATH; | task.integrator_branched = scene->get_integrator()->get_method() == Integrator::BRANCHED_PATH; | ||||
| task.adaptive_sampling.use = (scene->integrator->get_sampling_pattern() == | task.adaptive_sampling.use = (scene->get_integrator()->get_sampling_pattern() == | ||||
| SAMPLING_PATTERN_PMJ) && | SAMPLING_PATTERN_PMJ) && | ||||
| scene->dscene.data.film.pass_adaptive_aux_buffer; | scene->get_dscene().data.film.pass_adaptive_aux_buffer; | ||||
| task.adaptive_sampling.min_samples = scene->dscene.data.integrator.adaptive_min_samples; | task.adaptive_sampling.min_samples = scene->get_dscene().data.integrator.adaptive_min_samples; | ||||
| task.adaptive_sampling.adaptive_step = scene->dscene.data.integrator.adaptive_step; | task.adaptive_sampling.adaptive_step = scene->get_dscene().data.integrator.adaptive_step; | ||||
| /* Acquire render tiles by default. */ | /* Acquire render tiles by default. */ | ||||
| task.tile_types = RenderTile::PATH_TRACE; | task.tile_types = RenderTile::PATH_TRACE; | ||||
| if (need_denoise) { | if (need_denoise) { | ||||
| task.denoising = params.denoising; | task.denoising = params.denoising; | ||||
| task.pass_stride = scene->film->get_pass_stride(); | task.pass_stride = scene->get_film()->get_pass_stride(); | ||||
| task.target_pass_stride = task.pass_stride; | task.target_pass_stride = task.pass_stride; | ||||
| task.pass_denoising_data = scene->film->get_denoising_data_offset(); | task.pass_denoising_data = scene->get_film()->get_denoising_data_offset(); | ||||
| task.pass_denoising_clean = scene->film->get_denoising_clean_offset(); | task.pass_denoising_clean = scene->get_film()->get_denoising_clean_offset(); | ||||
| task.denoising_from_render = true; | task.denoising_from_render = true; | ||||
| if (tile_manager.schedule_denoising) { | if (tile_manager.schedule_denoising) { | ||||
| /* Acquire denoising tiles during rendering. */ | /* Acquire denoising tiles during rendering. */ | ||||
| task.tile_types |= RenderTile::DENOISE; | task.tile_types |= RenderTile::DENOISE; | ||||
| } | } | ||||
| else { | else { | ||||
| assert(buffers); | assert(buffers); | ||||
| /* Schedule rendering and wait for it to finish. */ | /* Schedule rendering and wait for it to finish. */ | ||||
| device->task_add(task); | device->task_add(task); | ||||
| device->task_wait(); | device->task_wait(); | ||||
| /* Then run denoising on the whole image at once. */ | /* Then run denoising on the whole image at once. */ | ||||
| task.type = DeviceTask::DENOISE_BUFFER; | task.type = DeviceTask::DENOISE_BUFFER; | ||||
| task.x = tile_manager.state.buffer.full_x; | task.x = tile_manager.state.buffer.get_full_x(); | ||||
| task.y = tile_manager.state.buffer.full_y; | task.y = tile_manager.state.buffer.get_full_y(); | ||||
| task.w = tile_manager.state.buffer.width; | task.w = tile_manager.state.buffer.get_width(); | ||||
| task.h = tile_manager.state.buffer.height; | task.h = tile_manager.state.buffer.get_height(); | ||||
| task.buffer = buffers->buffer.device_pointer; | task.buffer = buffers->get_buffer().device_pointer; | ||||
| task.sample = tile_manager.state.sample; | task.sample = tile_manager.state.sample; | ||||
| task.num_samples = tile_manager.state.num_samples; | task.num_samples = tile_manager.state.num_samples; | ||||
| tile_manager.state.buffer.get_offset_stride(task.offset, task.stride); | tile_manager.state.buffer.get_offset_stride(task.offset, task.stride); | ||||
| task.buffers = buffers; | task.buffers = buffers; | ||||
| } | } | ||||
| } | } | ||||
| device->task_add(task); | device->task_add(task); | ||||
| } | } | ||||
| void Session::copy_to_display_buffer(int sample) | void Session::copy_to_display_buffer(int sample) | ||||
| { | { | ||||
| /* add film conversion task */ | /* add film conversion task */ | ||||
| DeviceTask task(DeviceTask::FILM_CONVERT); | DeviceTask task(DeviceTask::FILM_CONVERT); | ||||
| task.x = tile_manager.state.buffer.full_x; | task.x = tile_manager.state.buffer.get_full_x(); | ||||
| task.y = tile_manager.state.buffer.full_y; | task.y = tile_manager.state.buffer.get_full_y(); | ||||
| task.w = tile_manager.state.buffer.width; | task.w = tile_manager.state.buffer.get_width(); | ||||
| task.h = tile_manager.state.buffer.height; | task.h = tile_manager.state.buffer.get_height(); | ||||
| task.rgba_byte = display->rgba_byte.device_pointer; | task.rgba_byte = display->get_rgba_byte().device_pointer; | ||||
| task.rgba_half = display->rgba_half.device_pointer; | task.rgba_half = display->get_rgba_half().device_pointer; | ||||
| task.buffer = buffers->buffer.device_pointer; | task.buffer = buffers->get_buffer().device_pointer; | ||||
| task.sample = sample; | task.sample = sample; | ||||
| tile_manager.state.buffer.get_offset_stride(task.offset, task.stride); | tile_manager.state.buffer.get_offset_stride(task.offset, task.stride); | ||||
| if (task.w > 0 && task.h > 0) { | if (task.w > 0 && task.h > 0) { | ||||
| device->task_add(task); | device->task_add(task); | ||||
| device->task_wait(); | device->task_wait(); | ||||
| /* set display to new size */ | /* set display to new size */ | ||||
| Show All 20 Lines | bool Session::update_progressive_refine(bool cancel) | ||||
| if (params.progressive_refine) { | if (params.progressive_refine) { | ||||
| foreach (Tile &tile, tile_manager.state.tiles) { | foreach (Tile &tile, tile_manager.state.tiles) { | ||||
| if (!tile.buffers) { | if (!tile.buffers) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| RenderTile rtile; | RenderTile rtile; | ||||
| rtile.x = tile_manager.state.buffer.full_x + tile.x; | rtile.set_x(tile_manager.state.buffer.get_full_x() + tile.x); | ||||
| rtile.y = tile_manager.state.buffer.full_y + tile.y; | rtile.set_y(tile_manager.state.buffer.get_full_y() + tile.y); | ||||
| rtile.w = tile.w; | rtile.set_w(tile.w); | ||||
| rtile.h = tile.h; | rtile.set_h(tile.h); | ||||
| rtile.sample = sample; | rtile.set_sample(sample); | ||||
| rtile.buffers = tile.buffers; | rtile.set_buffers(tile.buffers); | ||||
| 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); | ||||
| Show All 29 Lines | |||||