This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/intern/cycles/integrator/path_trace_work.cpp
Lukas Stockner 95aac5df73 Fix T101651: Cycles crashes when failing to initialize render device
The issue here was that PathTraceWork was set up before checking if
any error occurred, and it didn't account for the dummy device so
it called a non-implemented function.

This fix therefore avoids creating PathTraceWork for dummy devices
and checks for device creation errors earlier in the process.
2022-10-10 17:55:08 +02:00

200 lines
7.4 KiB
C++

/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "device/device.h"
#include "integrator/path_trace_display.h"
#include "integrator/path_trace_work.h"
#include "integrator/path_trace_work_cpu.h"
#include "integrator/path_trace_work_gpu.h"
#include "scene/film.h"
#include "scene/scene.h"
#include "session/buffers.h"
#include "kernel/types.h"
CCL_NAMESPACE_BEGIN
unique_ptr<PathTraceWork> PathTraceWork::create(Device *device,
Film *film,
DeviceScene *device_scene,
bool *cancel_requested_flag)
{
if (device->info.type == DEVICE_CPU) {
return make_unique<PathTraceWorkCPU>(device, film, device_scene, cancel_requested_flag);
}
if (device->info.type == DEVICE_DUMMY) {
/* Dummy devices can't perform any work. */
return nullptr;
}
return make_unique<PathTraceWorkGPU>(device, film, device_scene, cancel_requested_flag);
}
PathTraceWork::PathTraceWork(Device *device,
Film *film,
DeviceScene *device_scene,
bool *cancel_requested_flag)
: device_(device),
film_(film),
device_scene_(device_scene),
buffers_(make_unique<RenderBuffers>(device)),
effective_buffer_params_(buffers_->params),
cancel_requested_flag_(cancel_requested_flag)
{
}
PathTraceWork::~PathTraceWork()
{
}
RenderBuffers *PathTraceWork::get_render_buffers()
{
return buffers_.get();
}
void PathTraceWork::set_effective_buffer_params(const BufferParams &effective_full_params,
const BufferParams &effective_big_tile_params,
const BufferParams &effective_buffer_params)
{
effective_full_params_ = effective_full_params;
effective_big_tile_params_ = effective_big_tile_params;
effective_buffer_params_ = effective_buffer_params;
}
bool PathTraceWork::has_multiple_works() const
{
/* Assume if there are multiple works working on the same big tile none of the works gets the
* entire big tile to work on. */
return !(effective_big_tile_params_.width == effective_buffer_params_.width &&
effective_big_tile_params_.height == effective_buffer_params_.height &&
effective_big_tile_params_.full_x == effective_buffer_params_.full_x &&
effective_big_tile_params_.full_y == effective_buffer_params_.full_y);
}
void PathTraceWork::copy_to_render_buffers(RenderBuffers *render_buffers)
{
copy_render_buffers_from_device();
const int64_t width = effective_buffer_params_.width;
const int64_t height = effective_buffer_params_.height;
const int64_t pass_stride = effective_buffer_params_.pass_stride;
const int64_t row_stride = width * pass_stride;
const int64_t data_size = row_stride * height * sizeof(float);
const int64_t offset_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y;
const int64_t offset_in_floats = offset_y * row_stride;
const float *src = buffers_->buffer.data();
float *dst = render_buffers->buffer.data() + offset_in_floats;
memcpy(dst, src, data_size);
}
void PathTraceWork::copy_from_render_buffers(const RenderBuffers *render_buffers)
{
const int64_t width = effective_buffer_params_.width;
const int64_t height = effective_buffer_params_.height;
const int64_t pass_stride = effective_buffer_params_.pass_stride;
const int64_t row_stride = width * pass_stride;
const int64_t data_size = row_stride * height * sizeof(float);
const int64_t offset_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y;
const int64_t offset_in_floats = offset_y * row_stride;
const float *src = render_buffers->buffer.data() + offset_in_floats;
float *dst = buffers_->buffer.data();
memcpy(dst, src, data_size);
copy_render_buffers_to_device();
}
void PathTraceWork::copy_from_denoised_render_buffers(const RenderBuffers *render_buffers)
{
const int64_t width = effective_buffer_params_.width;
const int64_t offset_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y;
const int64_t offset = offset_y * width;
render_buffers_host_copy_denoised(
buffers_.get(), effective_buffer_params_, render_buffers, effective_buffer_params_, offset);
copy_render_buffers_to_device();
}
bool PathTraceWork::get_render_tile_pixels(const PassAccessor &pass_accessor,
const PassAccessor::Destination &destination)
{
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;
slice_destination.offset += offset_y * width;
return pass_accessor.get_render_tile_pixels(buffers_.get(), slice_destination);
}
bool PathTraceWork::set_render_tile_pixels(PassAccessor &pass_accessor,
const PassAccessor::Source &source)
{
const int offset_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y;
const int width = effective_buffer_params_.width;
PassAccessor::Source slice_source = source;
slice_source.offset += offset_y * width;
return pass_accessor.set_render_tile_pixels(buffers_.get(), slice_source);
}
PassAccessor::PassAccessInfo PathTraceWork::get_display_pass_access_info(PassMode pass_mode) const
{
const KernelFilm &kfilm = device_scene_->data.film;
const KernelBackground &kbackground = device_scene_->data.background;
const BufferParams &params = buffers_->params;
const BufferPass *display_pass = params.get_actual_display_pass(film_->get_display_pass());
PassAccessor::PassAccessInfo pass_access_info;
pass_access_info.type = display_pass->type;
pass_access_info.offset = PASS_UNUSED;
if (pass_mode == PassMode::DENOISED) {
pass_access_info.mode = PassMode::DENOISED;
pass_access_info.offset = params.get_pass_offset(pass_access_info.type, PassMode::DENOISED);
}
if (pass_access_info.offset == PASS_UNUSED) {
pass_access_info.mode = PassMode::NOISY;
pass_access_info.offset = params.get_pass_offset(pass_access_info.type);
}
pass_access_info.use_approximate_shadow_catcher = kfilm.use_approximate_shadow_catcher;
pass_access_info.use_approximate_shadow_catcher_background =
kfilm.use_approximate_shadow_catcher && !kbackground.transparent;
pass_access_info.show_active_pixels = film_->get_show_active_pixels();
return pass_access_info;
}
PassAccessor::Destination PathTraceWork::get_display_destination_template(
const PathTraceDisplay *display) const
{
PassAccessor::Destination destination(film_->get_display_pass());
const int2 display_texture_size = display->get_texture_size();
const int texture_x = effective_buffer_params_.full_x - effective_big_tile_params_.full_x +
effective_buffer_params_.window_x - effective_big_tile_params_.window_x;
const int texture_y = effective_buffer_params_.full_y - effective_big_tile_params_.full_y +
effective_buffer_params_.window_y - effective_big_tile_params_.window_y;
destination.offset = texture_y * display_texture_size.x + texture_x;
destination.stride = display_texture_size.x;
return destination;
}
CCL_NAMESPACE_END