diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-01-09 20:58:01 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-01-09 20:58:01 +0400 |
commit | d7932ceea82a3c2277a179c00ca72ecb3cfb97cb (patch) | |
tree | 933570102e52c7562b87534e87c0c38bb5eb47ec /intern/cycles/blender | |
parent | 47d9c6689be0448b898d18a1e810d2150867938b (diff) |
Cycles: multi GPU rendering support.
The rendering device is now set in User Preferences > System, where you can
choose between OpenCL/CUDA and devices. Per scene you can then still choose
to use CPU or GPU rendering.
Load balancing still needs to be improved, now it just splits the entire
render in two, that will be done in a separate commit.
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/CCL_api.h | 46 | ||||
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/blender/addon/engine.py | 3 | ||||
-rw-r--r-- | intern/cycles/blender/addon/enums.py | 24 | ||||
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 3 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 16 | ||||
-rw-r--r-- | intern/cycles/blender/blender_python.cpp | 73 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 19 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 7 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 50 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.h | 2 |
11 files changed, 152 insertions, 92 deletions
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h new file mode 100644 index 00000000000..469d63d1530 --- /dev/null +++ b/intern/cycles/blender/CCL_api.h @@ -0,0 +1,46 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CCL_API_H +#define CCL_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* returns a list of devices for selection, array is name NULL pointer + * terminated and must not be freed */ + +typedef struct CCLDeviceInfo { + const char *identifier; + const char *name; + int value; +} CCLDeviceInfo; + +CCLDeviceInfo *CCL_compute_device_list(int opencl); + +/* create python module _cycles used by addon */ + +void *CCL_python_module_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* CCL_API_H */ + diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 3b685346791..003c6c84f8f 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -27,6 +27,7 @@ set(SRC blender_shader.cpp blender_sync.cpp + CCL_api.h blender_sync.h blender_session.h blender_util.h diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 3d71c25d7ad..05b1f883594 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -35,6 +35,7 @@ def create(engine, data, scene, region=0, v3d=0, rv3d=0): import _cycles data = data.as_pointer() + userpref = bpy.context.user_preferences.as_pointer() scene = scene.as_pointer() if region: region = region.as_pointer() @@ -43,7 +44,7 @@ def create(engine, data, scene, region=0, v3d=0, rv3d=0): if rv3d: rv3d = rv3d.as_pointer() - engine.session = _cycles.create(engine.as_pointer(), data, scene, region, v3d, rv3d) + engine.session = _cycles.create(engine.as_pointer(), userpref, data, scene, region, v3d, rv3d) def free(engine): diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index a11f5ca0f87..da4c73a5d3b 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -20,29 +20,9 @@ from . import engine - -def get_gpu_device(): - available_devices = engine.available_devices() - cuda = 'cuda' in available_devices - opencl = 'opencl' in available_devices - if cuda and opencl: - gpu_string = "GPU" - elif cuda and not opencl: - gpu_string = "CUDA GPU" - else: - gpu_string = "OpenCL GPU" - - return gpu_string - devices = ( - ("CPU", "CPU", "Processor"), - ("GPU", get_gpu_device(), "Graphics card"), - ) - -gpu_type = ( - ("CUDA", "CUDA", "NVidia only"), - ("OPENCL", "OpenCL", ""), - ) + ("CPU", "CPU", "Use CPU for rendering"), + ("GPU", "GPU Compute", "Use GPU compute device for rendering, configured in user preferences")) feature_set = ( ("SUPPORTED", "Supported", "Only use finished and supported features"), diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 0ea7396f9c2..0b096c529b8 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -38,9 +38,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): cls.device = EnumProperty(name="Device", description="Device to use for rendering", items=enums.devices, default="CPU") - cls.gpu_type = EnumProperty(name="GPU Type", description="Processing system to use on the GPU", - items=enums.gpu_type, default="CUDA") - cls.feature_set = EnumProperty(name="Feature Set", description="Feature set to use for rendering", items=enums.feature_set, default="SUPPORTED") diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 6e73795666e..ea23e2b56a5 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -148,7 +148,6 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.prop(cscene, "debug_bvh_type", text="") sub.prop(cscene, "debug_use_spatial_splits") - class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): bl_label = "Layers" bl_options = {'DEFAULT_CLOSED'} @@ -712,19 +711,12 @@ def draw_device(self, context): cscene = scene.cycles layout.prop(cscene, "feature_set") - experimental = cscene.feature_set == 'EXPERIMENTAL' - - available_devices = engine.available_devices() - available_cuda = 'cuda' in available_devices - available_opencl = experimental and 'opencl' in available_devices - if available_cuda or available_opencl: + device_type = context.user_preferences.system.compute_device_type + if device_type == 'CUDA': + layout.prop(cscene, "device") + elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") - if cscene.device == 'GPU' and available_cuda and available_opencl: - layout.prop(cscene, "gpu_type") - if experimental and cscene.device == 'CPU' and engine.with_osl(): - layout.prop(cscene, "shading_system") - def draw_pause(self, context): layout = self.layout diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 90dab298dc3..6e892095387 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -18,9 +18,12 @@ #include <Python.h> +#include "CCL_api.h" + #include "blender_sync.h" #include "blender_session.h" +#include "util_foreach.h" #include "util_opengl.h" #include "util_path.h" @@ -40,9 +43,9 @@ static PyObject *init_func(PyObject *self, PyObject *args) static PyObject *create_func(PyObject *self, PyObject *args) { - PyObject *pyengine, *pydata, *pyscene, *pyregion, *pyv3d, *pyrv3d; + PyObject *pyengine, *pyuserpref, *pydata, *pyscene, *pyregion, *pyv3d, *pyrv3d; - if(!PyArg_ParseTuple(args, "OOOOOO", &pyengine, &pydata, &pyscene, &pyregion, &pyv3d, &pyrv3d)) + if(!PyArg_ParseTuple(args, "OOOOOOO", &pyengine, &pyuserpref, &pydata, &pyscene, &pyregion, &pyv3d, &pyrv3d)) return NULL; /* RNA */ @@ -50,6 +53,10 @@ static PyObject *create_func(PyObject *self, PyObject *args) RNA_pointer_create(NULL, &RNA_RenderEngine, (void*)PyLong_AsVoidPtr(pyengine), &engineptr); BL::RenderEngine engine(engineptr); + PointerRNA userprefptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyuserpref), &userprefptr); + BL::UserPreferences userpref(userprefptr); + PointerRNA dataptr; RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr); BL::BlendData data(dataptr); @@ -78,11 +85,11 @@ static PyObject *create_func(PyObject *self, PyObject *args) int width = region.width(); int height = region.height(); - session = new BlenderSession(engine, data, scene, v3d, rv3d, width, height); + session = new BlenderSession(engine, userpref, data, scene, v3d, rv3d, width, height); } else { /* offline session */ - session = new BlenderSession(engine, data, scene); + session = new BlenderSession(engine, userpref, data, scene); } return PyLong_FromVoidPtr(session); @@ -137,13 +144,12 @@ static PyObject *sync_func(PyObject *self, PyObject *value) static PyObject *available_devices_func(PyObject *self, PyObject *args) { - vector<DeviceType> types = Device::available_types(); + vector<DeviceInfo>& devices = Device::available_devices(); + PyObject *ret = PyTuple_New(devices.size()); - PyObject *ret = PyTuple_New(types.size()); - - for(size_t i = 0; i < types.size(); i++) { - string name = Device::string_from_type(types[i]); - PyTuple_SET_ITEM(ret, i, PyUnicode_FromString(name.c_str())); + for(size_t i = 0; i < devices.size(); i++) { + DeviceInfo& device = devices[i]; + PyTuple_SET_ITEM(ret, i, PyUnicode_FromString(device.description.c_str())); } return ret; @@ -169,11 +175,44 @@ static struct PyModuleDef module = { NULL, NULL, NULL, NULL }; -CCL_NAMESPACE_END +CCLDeviceInfo *compute_device_list(DeviceType type) +{ + /* device list stored static */ + static ccl::vector<CCLDeviceInfo> device_list; + static ccl::DeviceType device_type = DEVICE_NONE; + + /* create device list if it's not already done */ + if(type != device_type) { + ccl::vector<DeviceInfo>& devices = ccl::Device::available_devices(); + + device_type = type; + device_list.clear(); + + /* add devices */ + int i = 0; + + foreach(DeviceInfo& info, devices) { + if(info.type == type || + (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) { + CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++}; + device_list.push_back(cinfo); + } + } + + /* null terminate */ + if(!device_list.empty()) { + CCLDeviceInfo cinfo = {NULL, NULL, 0}; + device_list.push_back(cinfo); + } + } -extern "C" PyObject *CYCLES_initPython(); + return (device_list.empty())? NULL: &device_list[0]; +} -PyObject *CYCLES_initPython() + +CCL_NAMESPACE_END + +void *CCL_python_module_init() { PyObject *mod= PyModule_Create(&ccl::module); @@ -185,6 +224,12 @@ PyObject *CYCLES_initPython() Py_INCREF(Py_False); #endif - return mod; + return (void*)mod; +} + +CCLDeviceInfo *CCL_compute_device_list(int opencl) +{ + ccl::DeviceType type = (opencl)? ccl::DEVICE_OPENCL: ccl::DEVICE_CUDA; + return ccl::compute_device_list(type); } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index c7c35b537bd..b052fb3e195 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -39,8 +39,10 @@ CCL_NAMESPACE_BEGIN -BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_) -: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL), +BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_, + BL::BlendData b_data_, BL::Scene b_scene_) +: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_), + b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL), b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL) { /* offline render */ @@ -54,10 +56,11 @@ BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_ create_session(); } -BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, +BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_, + BL::BlendData b_data_, BL::Scene b_scene_, BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_) -: b_engine(b_engine_), b_data(b_data_), b_scene(b_scene_), b_v3d(b_v3d_), b_rv3d(b_rv3d_), - b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL) +: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_), + b_v3d(b_v3d_), b_rv3d(b_rv3d_), b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL) { /* 3d view render */ width = width_; @@ -77,7 +80,7 @@ BlenderSession::~BlenderSession() void BlenderSession::create_session() { SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); - SessionParams session_params = BlenderSync::get_session_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); /* reset status/progress */ last_status= ""; @@ -184,7 +187,7 @@ void BlenderSession::synchronize() { /* on session/scene parameter changes, we recreate session entirely */ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); - SessionParams session_params = BlenderSync::get_session_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); if(session->params.modified(session_params) || scene->params.modified(scene_params)) { @@ -258,7 +261,7 @@ bool BlenderSession::draw(int w, int h) /* reset if requested */ if(reset) { - SessionParams session_params = BlenderSync::get_session_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); session->reset(buffer_params, session_params.samples); diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 26fffcf3aff..b98e3ffed54 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -32,8 +32,10 @@ class Session; class BlenderSession { public: - BlenderSession(BL::RenderEngine b_engine, BL::BlendData b_data, BL::Scene b_scene); - BlenderSession(BL::RenderEngine b_engine, BL::BlendData b_data, BL::Scene b_scene, + BlenderSession(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, + BL::BlendData b_data, BL::Scene b_scene); + BlenderSession(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, + BL::BlendData b_data, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height); ~BlenderSession(); @@ -65,6 +67,7 @@ public: double last_redraw_time; BL::RenderEngine b_engine; + BL::UserPreferences b_userpref; BL::BlendData b_data; BL::Scene b_scene; BL::SpaceView3D b_v3d; diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 8f54f291cfb..c00320f0094 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -248,16 +248,7 @@ bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background) return (background)? false: get_boolean(cscene, "preview_pause"); } -static bool device_type_available(vector<DeviceInfo>& devices, DeviceType dtype) -{ - foreach(DeviceInfo& info, devices) - if(info.type == dtype) - return true; - - return false; -} - -SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background) +SessionParams BlenderSync::get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background) { SessionParams params; PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); @@ -266,29 +257,26 @@ SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background params.experimental = (RNA_enum_get(&cscene, "feature_set") != 0); /* device type */ - vector<DeviceInfo> devices = Device::available_devices(); - DeviceType device_type = DEVICE_CPU; + vector<DeviceInfo>& devices = Device::available_devices(); + + /* device default CPU */ + params.device = devices[0]; if(RNA_enum_get(&cscene, "device") != 0) { - - if(!params.experimental || RNA_enum_get(&cscene, "gpu_type") == 0) - device_type = DEVICE_CUDA; - else - device_type = DEVICE_OPENCL; - - if(device_type_available(devices, device_type)) - ; - else if(params.experimental && device_type_available(devices, DEVICE_OPENCL)) - device_type = DEVICE_OPENCL; - else if(device_type_available(devices, DEVICE_CUDA)) - device_type = DEVICE_CUDA; + /* find GPU device with given id */ + PointerRNA systemptr = b_userpref.system().ptr; + PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device"); + int device_id = b_userpref.system().compute_device(); + + const char *id; + + if(RNA_property_enum_identifier(NULL, &systemptr, deviceprop, device_id, &id)) { + foreach(DeviceInfo& info, devices) + if(info.id == id) + params.device = info; + } } - params.device = devices[0]; - foreach(DeviceInfo& info, devices) - if(info.type == device_type) - params.device = info; - /* Background */ params.background = background; @@ -316,6 +304,10 @@ SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background } else params.progressive = true; + + /* todo: multi device only works with single tiles now */ + if(params.device.type == DEVICE_MULTI) + params.tile_size = INT_MAX; return params; } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 60fdd7c386b..7b65376bd84 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -60,7 +60,7 @@ public: /* get parameters */ static SceneParams get_scene_params(BL::Scene b_scene, bool background); - static SessionParams get_session_params(BL::Scene b_scene, bool background); + static SessionParams get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background); static bool get_session_pause(BL::Scene b_scene, bool background); static BufferParams get_buffer_params(BL::Scene b_scene, BL::RegionView3D b_rv3d, int width, int height); |