Revision: 51588
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51588
Author:   nazgul
Date:     2012-10-24 14:43:29 +0000 (Wed, 24 Oct 2012)
Log Message:
-----------
Fix #32951: Progressive refine crashing Blender when used with multiple cuda 
devices

This time issue was caused by Save Buffers enabled and the reason blender
crashed was tiles generated by cycles didn't match tiles generated by
openexr.

Currently solved it in a way that background rendering will allocate tiles
in the same way render parts are generated in blender. Viewport rendering
will still be using sliced image, but it's more tricky to change and it's
no so big deal for now.

Modified Paths:
--------------
    trunk/blender/intern/cycles/render/session.cpp
    trunk/blender/intern/cycles/render/tile.cpp
    trunk/blender/intern/cycles/render/tile.h

Modified: trunk/blender/intern/cycles/render/session.cpp
===================================================================
--- trunk/blender/intern/cycles/render/session.cpp      2012-10-24 14:25:32 UTC 
(rev 51587)
+++ trunk/blender/intern/cycles/render/session.cpp      2012-10-24 14:43:29 UTC 
(rev 51588)
@@ -41,7 +41,7 @@
 Session::Session(const SessionParams& params_)
 : params(params_),
   tile_manager(params.progressive, params.samples, params.tile_size, 
params.start_resolution,
-       params.background == false || params.progressive_refine,
+       params.background == false || params.progressive_refine, 
params.background,
        max(params.device.multi_devices.size(), 1))
 {
        device_use_gl = ((params.device.type != DEVICE_CPU) && 
!params.background);

Modified: trunk/blender/intern/cycles/render/tile.cpp
===================================================================
--- trunk/blender/intern/cycles/render/tile.cpp 2012-10-24 14:25:32 UTC (rev 
51587)
+++ trunk/blender/intern/cycles/render/tile.cpp 2012-10-24 14:43:29 UTC (rev 
51588)
@@ -24,13 +24,14 @@
 CCL_NAMESPACE_BEGIN
 
 TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, 
int start_resolution_,
-                         int preserve_tile_device_, int num_devices_)
+                         bool preserve_tile_device_, bool background_, int 
num_devices_)
 {
        progressive = progressive_;
        tile_size = tile_size_;
        start_resolution = start_resolution_;
        num_devices = num_devices_;
        preserve_tile_device = preserve_tile_device_;
+       background = background_;
 
        BufferParams buffer_params;
        reset(buffer_params, 0);
@@ -72,18 +73,57 @@
        num_samples = num_samples_;
 }
 
-void TileManager::set_tiles()
+/* splits image into tiles and assigns equal amount of tiles to every render 
device */
+void TileManager::gen_tiles_global()
 {
        int resolution = state.resolution_divider;
        int image_w = max(1, params.width/resolution);
        int image_h = max(1, params.height/resolution);
+
+       state.tiles.clear();
+
+       int tile_w = (tile_size.x >= image_w)? 1: (image_w + tile_size.x - 
1)/tile_size.x;
+       int tile_h = (tile_size.y >= image_h)? 1: (image_h + tile_size.y - 
1)/tile_size.y;
+       int sub_w = (image_w + tile_w - 1)/tile_w;
+       int sub_h = (image_h + tile_h - 1)/tile_h;
+
+       int num_logical_devices = preserve_tile_device? num_devices: 1;
+       int num = min(image_h, num_logical_devices);
        int tile_index = 0;
 
+       int tiles_per_device = (tile_w * tile_h + num - 1) / num;
+       int cur_device = 0, cur_tiles = 0;
+
+       for(int tile_y = 0; tile_y < tile_h; tile_y++) {
+               for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
+                       int x = tile_x * sub_w;
+                       int y = tile_y * sub_h;
+                       int w = (tile_x == tile_w-1)? image_w - x: sub_w;
+                       int h = (tile_y == tile_h-1)? image_h - y: sub_h;
+
+                       state.tiles.push_back(Tile(tile_index, x, y, w, h, 
cur_device));
+                       cur_tiles++;
+
+                       if(cur_tiles == tiles_per_device) {
+                               cur_tiles = 0;
+                               cur_device++;
+                       }
+               }
+       }
+}
+
+/* slices image into as much pieces as how many devices are rendering this 
image */
+void TileManager::gen_tiles_sliced()
+{
+       int resolution = state.resolution_divider;
+       int image_w = max(1, params.width/resolution);
+       int image_h = max(1, params.height/resolution);
+
        state.tiles.clear();
 
        int num_logical_devices = preserve_tile_device? num_devices: 1;
-
        int num = min(image_h, num_logical_devices);
+       int tile_index = 0;
 
        for(int device = 0; device < num; device++) {
                int device_y = (image_h/num)*device;
@@ -105,7 +145,19 @@
                        }
                }
        }
+}
 
+void TileManager::set_tiles()
+{
+       int resolution = state.resolution_divider;
+       int image_w = max(1, params.width/resolution);
+       int image_h = max(1, params.height/resolution);
+
+       if(background)
+               gen_tiles_global();
+       else
+               gen_tiles_sliced();
+
        state.num_tiles = state.tiles.size();
 
        state.buffer.width = image_w;
@@ -126,16 +178,10 @@
        int image_h = max(1, params.height/resolution);
 
        int logical_device = preserve_tile_device? device: 0;
-       int num_logical_devices = preserve_tile_device? num_devices: 1;
 
-       int num = min(image_h, num_logical_devices);
+       int64_t centx = image_w / 2, centy = image_h / 2, tot = 1;
+       int64_t mindist = (int64_t) image_w * (int64_t) image_h;
 
-       int device_y = (image_h / num) * logical_device;
-       int device_h = (logical_device == num - 1) ? image_h - device * 
(image_h / num) : image_h / num;
-
-       int64_t centx = image_w / 2, centy = device_y + device_h / 2, tot = 1;
-       int64_t mindist = (int64_t) image_w * (int64_t) device_h;
-
        /* find center of rendering tiles, image center counts for 1 too */
        for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
                if(iter->rendering) {

Modified: trunk/blender/intern/cycles/render/tile.h
===================================================================
--- trunk/blender/intern/cycles/render/tile.h   2012-10-24 14:25:32 UTC (rev 
51587)
+++ trunk/blender/intern/cycles/render/tile.h   2012-10-24 14:43:29 UTC (rev 
51588)
@@ -59,7 +59,7 @@
        } state;
 
        TileManager(bool progressive, int num_samples, int2 tile_size, int 
start_resolution,
-                   int preserve_tile_device, int num_devices = 1);
+                   bool preserve_tile_device, bool background, int num_devices 
= 1);
        ~TileManager();
 
        void reset(BufferParams& params, int num_samples);
@@ -86,6 +86,22 @@
         */
        bool preserve_tile_device;
 
+       /* for background render tiles should exactly match render parts 
generated from
+        * blender side, which means image first gets split into tiles and then 
tiles are
+        * assigning to render devices
+        *
+        * however viewport rendering expects tiles to be allocated in a 
special way,
+        * meaning image is being sliced horizontally first and every device 
handles
+        * it's own slice
+        */
+       bool background;
+
+       /* splits image into tiles and assigns equal amount of tiles to every 
render device */
+       void gen_tiles_global();
+
+       /* slices image into as much pieces as how many devices are rendering 
this image */
+       void gen_tiles_sliced();
+
        list<Tile>::iterator next_center_tile(int device = 0);
 };
 

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to