intern/cycles/app/cycles_standalone.cpp | 412 ++++++++++++++++++++++++++++++-- intern/cycles/app/cycles_xml.cpp | 116 ++++++++- intern/cycles/app/cycles_xml.h | 13 + intern/cycles/device/device_cpu.cpp | 30 ++- intern/cycles/device/device_cuda.cpp | 6 +- intern/cycles/kernel/kernel_path.h | 45 ++-- intern/cycles/render/buffers.cpp | 20 ++ intern/cycles/render/buffers.h | 4 + intern/cycles/render/session.cpp | 91 +++++++ intern/cycles/render/session.h | 5 + intern/cycles/render/tile.cpp | 45 +++- intern/cycles/render/tile.h | 11 +- intern/cycles/util/util_progress.h | 3 + 13 files changed, 740 insertions(+), 61 deletions(-) diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp index 90333eb..dc7a684 100644 --- a/intern/cycles/app/cycles_standalone.cpp +++ b/intern/cycles/app/cycles_standalone.cpp @@ -22,6 +22,9 @@ #include "scene.h" #include "session.h" +#include "mesh.h" +#include "object.h" + #include "util_args.h" #include "util_foreach.h" #include "util_function.h" @@ -30,6 +33,7 @@ #include "util_string.h" #include "util_time.h" #include "util_transform.h" +#include "util_xml.h" #ifdef WITH_CYCLES_STANDALONE_GUI #include "util_view.h" @@ -37,6 +41,11 @@ #include "cycles_xml.h" + +// save file dialog +#include + + CCL_NAMESPACE_BEGIN struct Options { @@ -171,6 +180,7 @@ static void display_info(Progress& progress) sample = progress.get_sample(); progress.get_tile(tile, total_time, sample_time); progress.get_status(status, substatus); + int nopped=progress.nopped_tiles; if(substatus != "") status += ": " + substatus; @@ -183,8 +193,9 @@ static void display_info(Progress& progress) " Latency: %.4f" " Sample: %d" " Average: %.4f" - " Interactive: %s", - status.c_str(), total_time, latency, sample, sample_time, interactive.c_str()); + " Nopped: %i" + " Interactive: %s PRESS S TO SAVE THE IMAGE", + status.c_str(), total_time, latency, sample, sample_time, nopped, interactive.c_str()); view_display_info(str.c_str()); diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp index de554fb..f08e13c 100644 --- a/intern/cycles/app/cycles_xml.cpp +++ b/intern/cycles/app/cycles_xml.cpp @@ -506,6 +545,11 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug xml_read_float3(&normal->direction, node, "direction"); snode = normal; } + else if(string_iequals(node.name(), "bump")) { + BumpNode *bump = new BumpNode(); + xml_read_bool(&bump->invert, node, "invert"); + snode = bump; + } else if(string_iequals(node.name(), "mapping")) { snode = new MappingNode(); } diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index b0739dd..37cc3ee 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -175,10 +175,14 @@ public: break; } + int _sample=sample; + if ( tile.flags&RenderTile::TILE_FLAG_NOP ) + _sample = -sample-1+tile.num_samples; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { kernel_cpu_avx_path_trace(&kg, render_buffer, rng_state, - sample, x, y, tile.offset, tile.stride); + _sample, x, y, tile.offset, tile.stride); } } @@ -197,10 +201,14 @@ public: break; } + int _sample=sample; + if ( tile.flags&RenderTile::TILE_FLAG_NOP ) + _sample = -sample-1+tile.num_samples; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { kernel_cpu_sse41_path_trace(&kg, render_buffer, rng_state, - sample, x, y, tile.offset, tile.stride); + _sample, x, y, tile.offset, tile.stride); } } @@ -219,10 +227,14 @@ public: break; } + int _sample=sample; + if ( tile.flags&RenderTile::TILE_FLAG_NOP ) + _sample = -sample-1+tile.num_samples; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { kernel_cpu_sse3_path_trace(&kg, render_buffer, rng_state, - sample, x, y, tile.offset, tile.stride); + _sample, x, y, tile.offset, tile.stride); } } @@ -241,10 +253,14 @@ public: break; } + int _sample=sample; + if ( tile.flags&RenderTile::TILE_FLAG_NOP ) + _sample = -sample-1+tile.num_samples; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { kernel_cpu_sse2_path_trace(&kg, render_buffer, rng_state, - sample, x, y, tile.offset, tile.stride); + _sample, x, y, tile.offset, tile.stride); } } @@ -262,10 +278,14 @@ public: break; } + int _sample=sample; + if ( tile.flags&RenderTile::TILE_FLAG_NOP ) + _sample = -sample-1+tile.num_samples; + for(int y = tile.y; y < tile.y + tile.h; y++) { for(int x = tile.x; x < tile.x + tile.w; x++) { kernel_cpu_path_trace(&kg, render_buffer, rng_state, - sample, x, y, tile.offset, tile.stride); + _sample, x, y, tile.offset, tile.stride); } } diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 48d1c18..d2f5178 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -1019,7 +1019,11 @@ public: break; } - path_trace(tile, sample, branched); + int _sample = sample; + if ( tile.flags&RenderTile::TILE_FLAG_NOP ) + _sample = -sample-1+tile.num_samples; + + path_trace(tile, _sample, branched); tile.sample = sample + 1; diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index d760af1..b83d0c0 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -1425,20 +1425,26 @@ ccl_device void kernel_path_trace(KernelGlobals *kg, RNG rng; Ray ray; - kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray); - /* integrate */ float4 L; - if(ray.t != 0.0f) - L = kernel_path_integrate(kg, &rng, sample, ray, buffer); - else - L = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + if ( sample >= 0 ) { + kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray); + + if(ray.t != 0.0f) + L = kernel_path_integrate(kg, &rng, sample, ray, buffer); + else + L = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + path_rng_end(kg, rng_state, rng); + } else { + // take actual value + ccl_global float4 *buf = (ccl_global float4*)buffer; + L = (*buf) * (1.0f / (-1.0f*sample)); + } /* accumulate result in output buffer */ kernel_write_pass_float4(buffer, sample, L); - - path_rng_end(kg, rng_state, rng); } #ifdef __BRANCHED_PATH__ @@ -1457,20 +1463,29 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg, RNG rng; Ray ray; - kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray); - /* integrate */ float4 L; - if(ray.t != 0.0f) - L = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer); + if ( sample >= 0 ) + { + kernel_path_trace_setup(kg, rng_state, sample, x, y, &rng, &ray); + + if(ray.t != 0.0f) + L = kernel_branched_path_integrate(kg, &rng, sample, ray, buffer); + else + L = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + + path_rng_end(kg, rng_state, rng); + } else - L = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + { + // take actual value + ccl_global float4 *buf = (ccl_global float4*)buffer; + L = (*buf) * (1.0f / (-1.0f*sample)); + } /* accumulate result in output buffer */ kernel_write_pass_float4(buffer, sample, L); - - path_rng_end(kg, rng_state, rng); } #endif diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 9fcd9fa..c963321 100644 @@ -266,6 +293,9 @@ void Session::run_gpu() /* update status and timing */ update_status_time(); + /* determine tiles to refine */ + nop_tiles(); + /* path trace */ path_trace(); @@ -370,6 +400,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile) rtile.start_sample = tile_manager.state.sample; rtile.num_samples = tile_manager.state.num_samples; rtile.resolution = tile_manager.state.resolution_divider; + rtile.flags = tile.flags; tile_lock.unlock(); @@ -465,6 +496,63 @@ void Session::release_tile(RenderTile& rtile) update_status_time(); } +void Session::nop_tiles() +{ + return; + int minsample=5; + int noppedtiles=0; + float eps = .1f; + + buffers->copy_from_device(); + if ( buffers->buffer.size() == last_buffers.size() && + tile_manager.state.resolution_divider==1 && + tile_manager.state.sample>=minsample ) { + // compare to last_buffer, tilewise + int offset,stride; + tile_manager.params.get_offset_stride(offset, stride); + Tile* tile=0; + float4* A = (float4*)last_buffers.data_pointer; + float4* B = (float4*)buffers->buffer.data_pointer; + float avg_scale = 1.0f / (1.0f*tile_manager.state.sample-tile_manager.state.num_samples+1); + float dif_scale = 1.0f / (1.0f*tile_manager.state.last_num_samples); + for(int d=0; dw; x++) { + for(int y=0; yh; y++) { + int index = tile->x + x + (tile->y + y) * buffers->params.full_width; + + float4 dif = (B[index] - A[index]) * dif_scale; + float4 avg = B[index] * avg_scale; + float4 progress = dif-avg; + maxVariation = max( maxVariation, max( fabsf(progress.x), max(fabsf(progress.y), max(fabsf(progress.z), fabsf(progress.w))))); + if ( maxVariation > eps ) + break; + } + if ( maxVariation > eps ) + break; + } + if ( maxVariation > eps ) { + tile->flags &= ~Tile::TILE_FLAGS_NOP; + } else { + tile->flags |= Tile::TILE_FLAGS_NOP; + noppedtiles++; + } + } + } + progress.nopped_tiles = noppedtiles++; + // mark them as "not rendering" so device can process them + tile_manager.reiterate_tiles(); + } + + if ( tile_manager.state.resolution_divider==1 ) { + // copy to last buffer + last_buffers.resize( buffers->buffer.data_size ); + memcpy( (void*)last_buffers.data_pointer, (void*)buffers->buffer.data_pointer, buffers->buffer.data_size * 4 ); + } +} + void Session::run_cpu() { bool tiles_written = false; @@ -548,6 +636,9 @@ void Session::run_cpu() /* update status and timing */ update_status_time(); + /* determine tiles to refine */ + nop_tiles(); + /* path trace */ path_trace(); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 9da7a0aa..5b1c863 100644 @@ -158,6 +160,9 @@ protected: void path_trace(); void reset_(BufferParams& params, int samples); + device_vector last_buffers; + void nop_tiles(); + void run_cpu(); bool draw_cpu(BufferParams& params, DeviceDrawParams& draw_params); void reset_cpu(BufferParams& params, int samples); diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 72bcdf9..40c7508 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -63,6 +63,7 @@ void TileManager::reset(BufferParams& params_, int num_samples_) state.num_tiles = 0; state.num_rendered_tiles = 0; state.num_samples = 0; + state.last_num_samples = 0; state.resolution_divider = divider; state.tiles.clear(); } @@ -98,7 +99,7 @@ void TileManager::gen_tiles_global() int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; int h = (tile_y == tile_h-1)? image_h - y: tile_size.y; - state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device)); + state.tiles.push_back(Tile(tile_index, x, y, w, h, cur_device, 0)); cur_tiles++; if(cur_tiles == tiles_per_device) { @@ -136,7 +137,7 @@ void TileManager::gen_tiles_sliced() int w = (tile_x == tile_w-1)? image_w - x: tile_size.x; int h = (tile_y == tile_h-1)? device_h - y: tile_size.y; - state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device)); + state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device, 0)); } } } @@ -230,6 +231,14 @@ list::iterator TileManager::next_background_tile(int device, TileOrder til return best; } +void TileManager::reiterate_tiles() +{ + list::iterator iter; + for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) + iter->rendering = false; + state.num_rendered_tiles=0; +} + bool TileManager::next_tile(Tile& tile, int device) { list::iterator tile_it; @@ -250,6 +259,26 @@ bool TileManager::next_tile(Tile& tile, int device) return false; } +bool TileManager::next_tile(Tile** tile, int device) +{ + list::iterator tile_it; + + if (background) + tile_it = next_background_tile(device, tile_order); + else + tile_it = next_viewport_tile(device); + + if(tile_it != state.tiles.end()) { + tile_it->rendering = true; + *tile = &(*tile_it); + state.num_rendered_tiles++; + + return true; + } + + return false; +} + bool TileManager::done() { return (state.sample+state.num_samples >= num_samples && state.resolution_divider == 1); @@ -260,6 +289,8 @@ bool TileManager::next() if(done()) return false; + state.last_num_samples = state.num_samples; + if(progressive && state.resolution_divider > 1) { state.sample = 0; state.resolution_divider /= 2; @@ -267,12 +298,16 @@ bool TileManager::next() set_tiles(); } else { - state.sample++; - if(progressive) - state.num_samples = 1; + { + state.num_samples = 2; + state.sample += state.num_samples; + } else + { + state.sample++; state.num_samples = num_samples; + } state.resolution_divider = 1; set_tiles(); diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h index 7796518..ae8584b 100644 --- a/intern/cycles/render/tile.h +++ b/intern/cycles/render/tile.h @@ -32,12 +32,14 @@ public: int x, y, w, h; int device; bool rendering; + int flags; + enum TILE_FLAGS { TILE_FLAGS_NOP=1, }; Tile() {} - Tile(int index_, int x_, int y_, int w_, int h_, int device_) - : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} + Tile(int index_, int x_, int y_, int w_, int h_, int device_, int flags_) + : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false), flags(flags_) {} }; /* Tile order */ @@ -61,6 +63,7 @@ public: BufferParams buffer; int sample; int num_samples; + int last_num_samples; int resolution_divider; int num_tiles; int num_rendered_tiles; @@ -77,8 +80,12 @@ public: void set_samples(int num_samples); bool next(); bool next_tile(Tile& tile, int device = 0); + bool next_tile(Tile** tile, int device=0); bool done(); + void reiterate_tiles(); + int get_num_devices() { return num_devices; } + void set_tile_order(TileOrder tile_order_) { tile_order = tile_order_; } protected: diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index 5d1219b..a2acbc3 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -47,6 +47,7 @@ public: cancel = false; cancel_message = ""; cancel_cb = NULL; + nopped_tiles=0; } Progress(Progress& progress) @@ -232,6 +233,8 @@ public: update_cb = function; } + int nopped_tiles; + protected: thread_mutex progress_mutex; thread_mutex update_mutex;