Fix #32951: Progressive refine crashing Blender when used with multiple cuda

Issue was caused by offline rendering could have been allocated the same tile
to different devices and in this case buffers would become invalid.

Made it more clear in the code, so now it's  flag for tile manager to indicate
whether tiles should always be allocated for the same device or not.

Also cleaned a way how tile index for progressive refine is calculating,
which is now avoids tricky computation based on tile coordinate and it's
dimensions.
This commit is contained in:
Sergey Sharybin
2012-10-23 16:36:53 +00:00
parent e038a1c613
commit 933864da18
3 changed files with 39 additions and 24 deletions

View File

@@ -34,10 +34,15 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
/* Note about preserve_tile_device option for tile manager:
* progressive refine and viewport rendering does requires tiles to
* always be allocated for the same device
*/
Session::Session(const SessionParams& params_) Session::Session(const SessionParams& params_)
: params(params_), : params(params_),
tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution, tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution,
(params.background)? 1: max(params.device.multi_devices.size(), 1)) params.background == false || params.progressive_refine,
max(params.device.multi_devices.size(), 1))
{ {
device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background); device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
@@ -334,7 +339,7 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
/* get next tile from manager */ /* get next tile from manager */
Tile tile; Tile tile;
int device_num = (params.background)? 0: device->device_number(tile_device); int device_num = device->device_number(tile_device);
if(!tile_manager.next_tile(tile, device_num)) if(!tile_manager.next_tile(tile, device_num))
return false; return false;
@@ -378,20 +383,15 @@ bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
/* allocate buffers */ /* allocate buffers */
if(params.progressive_refine) { if(params.progressive_refine) {
int tile_x = rtile.x / params.tile_size.x;
int tile_y = rtile.y / params.tile_size.y;
int tile_index = tile_y * tile_manager.state.tile_w + tile_x;
tile_lock.lock(); tile_lock.lock();
if(tile_buffers.size() == 0) if(tile_buffers.size() == 0)
tile_buffers.resize(tile_manager.state.num_tiles, NULL); tile_buffers.resize(tile_manager.state.num_tiles, NULL);
tilebuffers = tile_buffers[tile_index]; tilebuffers = tile_buffers[tile.index];
if(tilebuffers == NULL) { if(tilebuffers == NULL) {
tilebuffers = new RenderBuffers(tile_device); tilebuffers = new RenderBuffers(tile_device);
tile_buffers[tile_index] = tilebuffers; tile_buffers[tile.index] = tilebuffers;
tilebuffers->reset(tile_device, buffer_params); tilebuffers->reset(tile_device, buffer_params);
} }

View File

@@ -23,12 +23,14 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_, int num_devices_) TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
int preserve_tile_device_, int num_devices_)
{ {
progressive = progressive_; progressive = progressive_;
tile_size = tile_size_; tile_size = tile_size_;
start_resolution = start_resolution_; start_resolution = start_resolution_;
num_devices = num_devices_; num_devices = num_devices_;
preserve_tile_device = preserve_tile_device_;
BufferParams buffer_params; BufferParams buffer_params;
reset(buffer_params, 0); reset(buffer_params, 0);
@@ -75,10 +77,13 @@ void TileManager::set_tiles()
int resolution = state.resolution_divider; int resolution = state.resolution_divider;
int image_w = max(1, params.width/resolution); int image_w = max(1, params.width/resolution);
int image_h = max(1, params.height/resolution); int image_h = max(1, params.height/resolution);
int tile_index = 0;
state.tiles.clear(); state.tiles.clear();
int num = min(image_h, num_devices); int num_logical_devices = preserve_tile_device? num_devices: 1;
int num = min(image_h, num_logical_devices);
for(int device = 0; device < num; device++) { for(int device = 0; device < num; device++) {
int device_y = (image_h/num)*device; int device_y = (image_h/num)*device;
@@ -90,20 +95,18 @@ void TileManager::set_tiles()
int sub_h = (device_h + tile_h - 1)/tile_h; int sub_h = (device_h + tile_h - 1)/tile_h;
for(int tile_y = 0; tile_y < tile_h; tile_y++) { for(int tile_y = 0; tile_y < tile_h; tile_y++) {
for(int tile_x = 0; tile_x < tile_w; tile_x++) { for(int tile_x = 0; tile_x < tile_w; tile_x++, tile_index++) {
int x = tile_x * sub_w; int x = tile_x * sub_w;
int y = tile_y * sub_h; int y = tile_y * sub_h;
int w = (tile_x == tile_w-1)? image_w - x: sub_w; int w = (tile_x == tile_w-1)? image_w - x: sub_w;
int h = (tile_y == tile_h-1)? device_h - y: sub_h; int h = (tile_y == tile_h-1)? device_h - y: sub_h;
state.tiles.push_back(Tile(x, y + device_y, w, h, device)); state.tiles.push_back(Tile(tile_index, x, y + device_y, w, h, device));
} }
} }
} }
state.num_tiles = state.tiles.size(); state.num_tiles = state.tiles.size();
state.tile_w = (tile_size.x >= image_w) ? 1 : (image_w + tile_size.x - 1) / tile_size.x;
state.tile_h = (tile_size.y >= image_h) ? 1 : (image_h + tile_size.y - 1) / tile_size.y;
state.buffer.width = image_w; state.buffer.width = image_w;
state.buffer.height = image_h; state.buffer.height = image_h;
@@ -122,10 +125,13 @@ list<Tile>::iterator TileManager::next_center_tile(int device)
int image_w = max(1, params.width/resolution); int image_w = max(1, params.width/resolution);
int image_h = max(1, params.height/resolution); int image_h = max(1, params.height/resolution);
int num = min(image_h, num_devices); int logical_device = preserve_tile_device? device: 0;
int num_logical_devices = preserve_tile_device? num_devices: 1;
int device_y = (image_h / num) * device; int num = min(image_h, num_logical_devices);
int device_h = (device == num - 1) ? image_h - device * (image_h / num) : image_h / num;
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 centx = image_w / 2, centy = device_y + device_h / 2, tot = 1;
int64_t mindist = (int64_t) image_w * (int64_t) device_h; int64_t mindist = (int64_t) image_w * (int64_t) device_h;
@@ -145,7 +151,7 @@ list<Tile>::iterator TileManager::next_center_tile(int device)
/* closest of the non-rendering tiles */ /* closest of the non-rendering tiles */
for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) { for(iter = state.tiles.begin(); iter != state.tiles.end(); iter++) {
if(iter->device == device && iter->rendering == false) { if(iter->device == logical_device && iter->rendering == false) {
Tile &cur_tile = *iter; Tile &cur_tile = *iter;
int64_t distx = centx - (cur_tile.x + cur_tile.w / 2); int64_t distx = centx - (cur_tile.x + cur_tile.w / 2);

View File

@@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN
class Tile { class Tile {
public: public:
int index;
int x, y, w, h; int x, y, w, h;
int device; int device;
bool rendering; bool rendering;
@@ -37,8 +38,8 @@ public:
Tile() Tile()
{} {}
Tile(int x_, int y_, int w_, int h_, int device_) Tile(int index_, int x_, int y_, int w_, int h_, int device_)
: x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {} : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), rendering(false) {}
}; };
/* Tile Manager */ /* Tile Manager */
@@ -54,12 +55,11 @@ public:
int resolution_divider; int resolution_divider;
int num_tiles; int num_tiles;
int num_rendered_tiles; int num_rendered_tiles;
int tile_w;
int tile_h;
list<Tile> tiles; list<Tile> tiles;
} state; } state;
TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution, int num_devices = 1); TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution,
int preserve_tile_device, int num_devices = 1);
~TileManager(); ~TileManager();
void reset(BufferParams& params, int num_samples); void reset(BufferParams& params, int num_samples);
@@ -77,6 +77,15 @@ protected:
int start_resolution; int start_resolution;
int num_devices; int num_devices;
/* in some cases it is important that the same tile will be returned for the same
* device it was originally generated for (i.e. viewport rendering when buffer is
* allocating once for tile and then always used by it)
*
* in other cases any tile could be handled by any device (i.e. final rendering
* without progressive refine)
*/
bool preserve_tile_device;
list<Tile>::iterator next_center_tile(int device = 0); list<Tile>::iterator next_center_tile(int device = 0);
}; };