diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp index 0293223864d..ffcaef0b2a9 100644 --- a/intern/cycles/blender/blender_device.cpp +++ b/intern/cycles/blender/blender_device.cpp @@ -47,8 +47,7 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen vector devices = Device::available_devices(BlenderSession::device_override); if (devices.empty()) { - printf("Found no Cycles device of the specified type, falling back to CPU...\n"); - return Device::available_devices(DEVICE_MASK_CPU).front(); + return Device::dummy_device("Found no Cycles device of the specified type"); } int threads = blender_device_threads(b_scene); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index c2bdec0e53d..8214ff7d532 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -472,6 +472,11 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) { b_depsgraph = b_depsgraph_; + if (session->progress.get_cancel()) { + update_status_progress(); + return; + } + /* set callback to write out render results */ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1); session->update_render_tile_cb = function_bind( diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt index cc54f64b1bb..928249931a3 100644 --- a/intern/cycles/device/CMakeLists.txt +++ b/intern/cycles/device/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC device_cpu.cpp device_cuda.cpp device_denoising.cpp + device_dummy.cpp device_memory.cpp device_multi.cpp device_opencl.cpp diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 407f73e8451..eb8fb8040e3 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -375,7 +375,7 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool } #endif - Device *device; + Device *device = NULL; switch (info.type) { case DEVICE_CPU: @@ -385,16 +385,12 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool case DEVICE_CUDA: if (device_cuda_init()) device = device_cuda_create(info, stats, profiler, background); - else - device = NULL; break; #endif #ifdef WITH_OPTIX case DEVICE_OPTIX: if (device_optix_init()) device = device_optix_create(info, stats, profiler, background); - else - device = NULL; break; #endif #ifdef WITH_NETWORK @@ -406,12 +402,14 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool case DEVICE_OPENCL: if (device_opencl_init()) device = device_opencl_create(info, stats, profiler, background); - else - device = NULL; break; #endif default: - return NULL; + break; + } + + if (device == NULL) { + device = device_dummy_create(info, stats, profiler, background); } return device; @@ -549,6 +547,14 @@ vector Device::available_devices(uint mask) return devices; } +DeviceInfo Device::dummy_device(const string &error_msg) +{ + DeviceInfo info; + info.type = DEVICE_DUMMY; + info.error_msg = error_msg; + return info; +} + string Device::device_capabilities(uint mask) { thread_scoped_lock lock(device_mutex); diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index ddf608aa430..2006db02ce7 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -48,6 +48,7 @@ enum DeviceType { DEVICE_NETWORK, DEVICE_MULTI, DEVICE_OPTIX, + DEVICE_DUMMY, }; enum DeviceTypeMask { @@ -87,6 +88,7 @@ class DeviceInfo { int cpu_threads; vector multi_devices; vector denoising_devices; + string error_msg; DeviceInfo() { @@ -471,6 +473,7 @@ class Device { static string string_from_type(DeviceType type); static vector available_types(); static vector available_devices(uint device_type_mask = DEVICE_MASK_ALL); + static DeviceInfo dummy_device(const string &error_msg = ""); static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL); static DeviceInfo get_multi_device(const vector &subdevices, int threads, diff --git a/intern/cycles/device/device_dummy.cpp b/intern/cycles/device/device_dummy.cpp new file mode 100644 index 00000000000..5112fc152e5 --- /dev/null +++ b/intern/cycles/device/device_dummy.cpp @@ -0,0 +1,83 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "device/device.h" +#include "device/device_intern.h" + +CCL_NAMESPACE_BEGIN + +/* Dummy device for when creating an appropriate rendering device fails. */ + +class DummyDevice : public Device { + public: + DummyDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_) + : Device(info_, stats_, profiler_, background_) + { + error_msg = info.error_msg; + } + + ~DummyDevice() + { + } + + virtual BVHLayoutMask get_bvh_layout_mask() const override + { + return 0; + } + + virtual void mem_alloc(device_memory &) override + { + } + + virtual void mem_copy_to(device_memory &) override + { + } + + virtual void mem_copy_from(device_memory &, int, int, int, int) override + { + } + + virtual void mem_zero(device_memory &) override + { + } + + virtual void mem_free(device_memory &) override + { + } + + virtual void const_copy_to(const char *, void *, size_t) override + { + } + + virtual void task_add(DeviceTask &) override + { + } + + virtual void task_wait() override + { + } + + virtual void task_cancel() override + { + } +}; + +Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background) +{ + return new DummyDevice(info, stats, profiler, background); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index 94d63e8f333..ecc79c5d7ee 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -35,6 +35,7 @@ bool device_cuda_init(); Device *device_cuda_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background); bool device_optix_init(); Device *device_optix_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background); +Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background); Device *device_network_create(DeviceInfo &info, Stats &stats, diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index c22e29043d3..fa3fd06ab27 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -61,22 +61,6 @@ Session::Session(const SessionParams ¶ms_) TaskScheduler::init(params.threads); - /* Create CPU/GPU devices. */ - device = Device::create(params.device, stats, profiler, params.background); - - /* Create buffers for interactive rendering. */ - if (params.background && !params.write_render_cb) { - buffers = NULL; - display = NULL; - } - else { - buffers = new RenderBuffers(device); - display = new DisplayBuffer(device, params.display_buffer_linear); - } - - /* Validate denoising parameters. */ - set_denoising(params.denoising); - session_thread = NULL; scene = NULL; @@ -90,6 +74,26 @@ Session::Session(const SessionParams ¶ms_) gpu_draw_ready = false; gpu_need_display_buffer_update = false; pause = false; + + buffers = NULL; + display = NULL; + + /* Validate denoising parameters. */ + set_denoising(params.denoising); + + /* Create CPU/GPU devices. */ + device = Device::create(params.device, stats, profiler, params.background); + + if (!device->error_message().empty()) { + progress.set_error(device->error_message()); + return; + } + + /* Create buffers for interactive rendering. */ + if (!(params.background && !params.write_render_cb)) { + buffers = new RenderBuffers(device); + display = new DisplayBuffer(device, params.display_buffer_linear); + } } Session::~Session() @@ -110,7 +114,7 @@ Session::~Session() wait(); } - if (params.write_render_cb) { + if (buffers && params.write_render_cb) { /* Copy to display buffer and write out image if requested */ delete display;