From 47fb31404fcb7b3244d3a575807a5084996802cb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 29 Aug 2011 10:21:10 +0000 Subject: [PATCH] Cycles: preview passes setting to set the max number of passes to render in the viewport working now, set to 0 for unlimited (well, actually 2147483647). --- intern/cycles/blender/addon/ui.py | 18 +-- .../cycles/kernel/osl/nodes/node_holdout.osl | 28 ++++ intern/cycles/render/session.cpp | 145 +++++++++++++----- intern/cycles/render/session.h | 5 + 4 files changed, 145 insertions(+), 51 deletions(-) create mode 100644 intern/cycles/kernel/osl/nodes/node_holdout.osl diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index a1363ece854..8da478d45a1 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -43,16 +43,15 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, bpy.types.Panel): split = layout.split() col = split.column() - col.prop(cscene, "passes", text="Render Passes") - #sub = col.row() - #sub.active = cscene.preview_passes >= 1 - #sub.prop(cscene, "preview_passes") + sub = col.column(align=True) + sub.prop(cscene, "passes", text="Render Passes") + sub.prop(cscene, "preview_passes") col.prop(cscene, "no_caustics") col = split.column() - col = col.column(align=True) - col.prop(cscene, "max_bounces") - col.prop(cscene, "min_bounces") + sub = col.column(align=True) + sub.prop(cscene, "max_bounces") + sub.prop(cscene, "min_bounces") #row = col.row() #row.prop(cscene, "blur_caustics") @@ -74,9 +73,10 @@ class CyclesRender_PT_film(CyclesButtonsPanel, bpy.types.Panel): col.prop(cscene, "transparent") col = split.column() - col.prop(cscene, "filter_type", text="") + sub = col.column(align=True) + sub.prop(cscene, "filter_type", text="") if cscene.filter_type != 'BOX': - col.prop(cscene, "filter_width", text="Width") + sub.prop(cscene, "filter_width", text="Width") class CyclesRender_PT_performance(CyclesButtonsPanel, bpy.types.Panel): bl_label = "Performance" diff --git a/intern/cycles/kernel/osl/nodes/node_holdout.osl b/intern/cycles/kernel/osl/nodes/node_holdout.osl new file mode 100644 index 00000000000..69f8d85a82e --- /dev/null +++ b/intern/cycles/kernel/osl/nodes/node_holdout.osl @@ -0,0 +1,28 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "stdosl.h" + +shader node_background( + color Color = color(0.8, 0.8, 0.8), + float Strength = 1.0, + output closure color Background = background()) +{ + Background = Color*Strength*background(); +} + diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 5890714d740..274c61a283e 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -57,6 +57,7 @@ Session::Session(const SessionParams& params_) display_outdated = false; gpu_draw_ready = false; gpu_need_tonemap = false; + pause = false; } Session::~Session() @@ -65,6 +66,7 @@ Session::~Session() progress.set_cancel("Exiting"); gpu_need_tonemap = false; gpu_need_tonemap_cond.notify_all(); + set_pause(false); wait(); } @@ -111,6 +113,8 @@ void Session::reset_gpu(int w, int h, int passes) gpu_need_tonemap = false; gpu_need_tonemap_cond.notify_all(); + + pause_cond.notify_all(); } bool Session::draw_gpu(int w, int h) @@ -150,52 +154,72 @@ void Session::run_gpu() reset_time = time_dt(); while(!progress.get_cancel()) { + /* advance to next tile */ bool done = !tile_manager.next(); - if(done && params.background) - break; + /* any work left? */ + if(done) { + /* if in background mode, we can stop immediately */ + if(params.background) { + break; + } + else { + /* in interactive mode, we wait until woken up */ + thread_scoped_lock pause_lock(pause_mutex); + pause_cond.wait(pause_lock); + } + } + else { + /* test for pause and wait until woken up */ + thread_scoped_lock pause_lock(pause_mutex); + while(pause) + pause_cond.wait(pause_lock); + } - /* todo: wait when done in interactive mode */ + { + /* buffers mutex is locked entirely while rendering each + pass, and released/reacquired on each iteration to allow + reset and draw in between */ + thread_scoped_lock buffers_lock(buffers->mutex); - /* buffers mutex is locked entirely while rendering each - pass, and released/reacquired on each iteration to allow - reset and draw in between */ - thread_scoped_lock buffers_lock(buffers->mutex); + /* update scene */ + update_scene(); + if(progress.get_cancel()) + break; - /* update scene */ - update_scene(); - if(progress.get_cancel()) - break; + /* update status and timing */ + update_status_time(); - /* update status and timing */ - update_status_time(); + /* path trace */ + foreach(Tile& tile, tile_manager.state.tiles) { + path_trace(tile); - /* path trace */ - foreach(Tile& tile, tile_manager.state.tiles) { - path_trace(tile); + device->task_wait(); - device->task_wait(); + if(progress.get_cancel()) + break; + } + + /* update status and timing */ + update_status_time(); + + gpu_need_tonemap = true; + gpu_draw_ready = true; + progress.set_update(); + + /* wait for tonemap */ + if(!params.background) { + while(gpu_need_tonemap) { + if(progress.get_cancel()) + break; + + gpu_need_tonemap_cond.wait(buffers_lock); + } + } if(progress.get_cancel()) break; } - - gpu_need_tonemap = true; - gpu_draw_ready = true; - progress.set_update(); - - /* wait for tonemap */ - if(!params.background) { - while(gpu_need_tonemap) { - if(progress.get_cancel()) - break; - - gpu_need_tonemap_cond.wait(buffers_lock); - } - } - - if(progress.get_cancel()) - break; } } @@ -213,6 +237,8 @@ void Session::reset_cpu(int w, int h, int passes) delayed_reset.passes = passes; delayed_reset.do_reset = true; device->task_cancel(); + + pause_cond.notify_all(); } bool Session::draw_cpu(int w, int h) @@ -249,14 +275,33 @@ void Session::run_cpu() } while(!progress.get_cancel()) { + /* advance to next tile */ bool done = !tile_manager.next(); + bool need_tonemap = false; - if(done && params.background) - break; + /* any work left? */ + if(done) { + /* if in background mode, we can stop immediately */ + if(params.background) { + break; + } + else { + /* in interactive mode, we wait until woken up */ + thread_scoped_lock pause_lock(pause_mutex); + pause_cond.wait(pause_lock); + } + } + else { + /* test for pause and wait until woken up */ + thread_scoped_lock pause_lock(pause_mutex); + while(pause) + pause_cond.wait(pause_lock); + } - /* todo: wait when done in interactive mode */ - - { + if(!done) { + /* buffers mutex is locked entirely while rendering each + pass, and released/reacquired on each iteration to allow + reset and draw in between */ thread_scoped_lock buffers_lock(buffers->mutex); /* update scene */ @@ -267,9 +312,14 @@ void Session::run_cpu() /* update status and timing */ update_status_time(); - /* path trace all tiles */ + /* path trace */ foreach(Tile& tile, tile_manager.state.tiles) path_trace(tile); + + /* update status and timing */ + update_status_time(); + + need_tonemap = true; } device->task_wait(); @@ -284,7 +334,7 @@ void Session::run_cpu() delayed_reset.do_reset = false; reset_(delayed_reset.w, delayed_reset.h, delayed_reset.passes); } - else { + else if(need_tonemap) { /* tonemap only if we do not reset, we don't we don't want to show the result of an incomplete pass*/ tonemap(); @@ -357,10 +407,21 @@ void Session::set_passes(int passes) if(passes != params.passes) { params.passes = passes; tile_manager.set_passes(passes); - /* todo: awake in paused loop */ + + pause_cond.notify_all(); } } +void Session::set_pause(bool pause_) +{ + { + thread_scoped_lock pause_lock(pause_mutex); + pause = pause_; + } + + pause_cond.notify_all(); +} + void Session::wait() { session_thread->join(); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 18983f55353..3aaaeedf0c5 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -109,6 +109,7 @@ public: bool ready_to_reset(); void reset(int w, int h, int passes); void set_passes(int passes); + void set_pause(bool pause); protected: struct DelayedReset { @@ -146,6 +147,10 @@ protected: volatile bool gpu_need_tonemap; thread_condition_variable gpu_need_tonemap_cond; + bool pause; + thread_condition_variable pause_cond; + thread_mutex pause_mutex; + double start_time; double reset_time; double preview_time;