Fix T91994: Cycles crash when rendering on multiple devices

The overscan change from D12599 lacked proper handling of window
when slicing buffer for multiple devices.
This commit is contained in:
Sergey Sharybin 2021-10-07 15:06:26 +02:00
parent 7fc11744e6
commit 123255be6b
Notes: blender-bot 2023-02-14 06:27:47 +01:00
Referenced by issue #91994, Blender 3.0 Crash when Cycles rendering GPU+CPU
3 changed files with 31 additions and 11 deletions

View File

@ -234,42 +234,53 @@ template<typename Callback>
static void foreach_sliced_buffer_params(const vector<unique_ptr<PathTraceWork>> &path_trace_works,
const vector<WorkBalanceInfo> &work_balance_infos,
const BufferParams &buffer_params,
const int overscan,
const Callback &callback)
{
const int num_works = path_trace_works.size();
const int height = buffer_params.height;
const int window_height = buffer_params.window_height;
int current_y = 0;
for (int i = 0; i < num_works; ++i) {
const double weight = work_balance_infos[i].weight;
const int slice_height = max(lround(height * weight), 1);
const int slice_window_full_y = buffer_params.full_y + buffer_params.window_y + current_y;
const int slice_window_height = max(lround(window_height * weight), 1);
/* Disallow negative values to deal with situations when there are more compute devices than
* scan-lines. */
const int remaining_height = max(0, height - current_y);
const int remaining_window_height = max(0, window_height - current_y);
BufferParams slice_params = buffer_params;
slice_params.full_y = max(slice_window_full_y - overscan, buffer_params.full_y);
slice_params.window_y = slice_window_full_y - slice_params.full_y;
BufferParams slide_params = buffer_params;
slide_params.full_y = buffer_params.full_y + current_y;
if (i < num_works - 1) {
slide_params.height = min(slice_height, remaining_height);
slice_params.window_height = min(slice_window_height, remaining_window_height);
}
else {
slide_params.height = remaining_height;
slice_params.window_height = remaining_window_height;
}
slide_params.update_offset_stride();
slice_params.height = slice_params.window_y + slice_params.window_height + overscan;
slice_params.height = min(slice_params.height,
buffer_params.height + buffer_params.full_y - slice_params.full_y);
callback(path_trace_works[i].get(), slide_params);
slice_params.update_offset_stride();
current_y += slide_params.height;
callback(path_trace_works[i].get(), slice_params);
current_y += slice_params.window_height;
}
}
void PathTrace::update_allocated_work_buffer_params()
{
const int overscan = tile_manager_.get_tile_overscan();
foreach_sliced_buffer_params(path_trace_works_,
work_balance_infos_,
big_tile_params_,
overscan,
[](PathTraceWork *path_trace_work, const BufferParams &params) {
RenderBuffers *buffers = path_trace_work->get_render_buffers();
buffers->reset(params);
@ -306,9 +317,12 @@ void PathTrace::update_effective_work_buffer_params(const RenderWork &render_wor
const BufferParams scaled_big_tile_params = scale_buffer_params(big_tile_params_,
resolution_divider);
const int overscan = tile_manager_.get_tile_overscan();
foreach_sliced_buffer_params(path_trace_works_,
work_balance_infos_,
scaled_big_tile_params,
overscan,
[&](PathTraceWork *path_trace_work, const BufferParams params) {
path_trace_work->set_effective_buffer_params(
scaled_full_params, scaled_big_tile_params, params);

View File

@ -134,7 +134,8 @@ void PathTraceWork::copy_from_denoised_render_buffers(const RenderBuffers *rende
bool PathTraceWork::get_render_tile_pixels(const PassAccessor &pass_accessor,
const PassAccessor::Destination &destination)
{
const int offset_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y;
const int offset_y = (effective_buffer_params_.full_y + effective_buffer_params_.window_y) -
(effective_big_tile_params_.full_y + effective_big_tile_params_.window_y);
const int width = effective_buffer_params_.width;
PassAccessor::Destination slice_destination = destination;

View File

@ -81,6 +81,11 @@ class TileManager {
return tile_state_.num_tiles > 1;
}
inline int get_tile_overscan() const
{
return overscan_;
}
bool next();
bool done();