diff options
30 files changed, 361 insertions, 148 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); diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 83600120fdd..1f0be1599bf 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -110,7 +110,7 @@ void Device::pixels_alloc(device_memory& mem) void Device::pixels_copy_from(device_memory& mem, int y, int w, int h) { - mem_copy_from(mem, sizeof(uint8_t)*4*y*w, sizeof(uint8_t)*4*w*h); + mem_copy_from(mem, y, w, h, sizeof(uint8_t)*4); } void Device::pixels_free(device_memory& mem) diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 51505aa9cb9..b8fea4c4c69 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -111,7 +111,7 @@ public: virtual void mem_alloc(device_memory& mem, MemoryType type) = 0; virtual void mem_copy_to(device_memory& mem) = 0; virtual void mem_copy_from(device_memory& mem, - size_t offset, size_t size) = 0; + int y, int w, int h, int elem) = 0; virtual void mem_zero(device_memory& mem) = 0; virtual void mem_free(device_memory& mem) = 0; diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index c93c6ff17da..e29266b0a7d 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -92,7 +92,7 @@ public: /* no-op */ } - void mem_copy_from(device_memory& mem, size_t offset, size_t size) + void mem_copy_from(device_memory& mem, int y, int w, int h, int elem) { /* no-op */ } diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp index 73d87ae4a2e..55b467fc856 100644 --- a/intern/cycles/device/device_cuda.cpp +++ b/intern/cycles/device/device_cuda.cpp @@ -341,9 +341,11 @@ public: cuda_pop_context(); } - void mem_copy_from(device_memory& mem, size_t offset, size_t size) + void mem_copy_from(device_memory& mem, int y, int w, int h, int elem) { - /* todo: offset is ignored */ + size_t offset = elem*y*w; + size_t size = elem*w*h; + cuda_push_context(); cuda_assert(cuMemcpyDtoH((uchar*)mem.data_pointer + offset, (CUdeviceptr)((uchar*)mem.device_pointer + offset), size)) @@ -863,6 +865,8 @@ void device_cuda_info(vector<DeviceInfo>& devices) if(cuDeviceGetCount(&count) != CUDA_SUCCESS) return; + vector<DeviceInfo> display_devices; + for(int num = 0; num < count; num++) { char name[256]; int attr; @@ -878,11 +882,16 @@ void device_cuda_info(vector<DeviceInfo>& devices) info.num = num; /* if device has a kernel timeout, assume it is used for display */ - if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) + if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) { info.display_device = true; - - devices.push_back(info); + display_devices.push_back(info); + } + else + devices.push_back(info); } + + if(!display_devices.empty()) + devices.insert(devices.end(), display_devices.begin(), display_devices.end()); } CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index f8b512f209c..41d0e268526 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -163,15 +163,18 @@ public: mem.device_pointer = tmp; } - void mem_copy_from(device_memory& mem, size_t offset, size_t size) + void mem_copy_from(device_memory& mem, int y, int w, int h, int elem) { device_ptr tmp = mem.device_pointer; + int i = 0, sub_h = h/devices.size(); - /* todo: how does this work? */ foreach(SubDevice& sub, devices) { + int sy = y + i*sub_h; + int sh = (i == (int)devices.size() - 1)? h - sub_h*i: sub_h; + mem.device_pointer = sub.ptr_map[tmp]; - sub.device->mem_copy_from(mem, offset, size); - break; + sub.device->mem_copy_from(mem, sy, w, sh, elem); + i++; } mem.device_pointer = tmp; @@ -332,37 +335,39 @@ Device *device_multi_create(DeviceInfo& info, bool background) return new MultiDevice(info, background); } -static void device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool skip_display, const char *id_fmt, int num) +static void device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool with_display, const char *id_fmt, int num) { DeviceInfo info; /* create map to find duplicate descriptions */ map<string, int> dupli_map; map<string, int>::iterator dt; - int num_added = 0, num_skipped = 0; + int num_added = 0, num_display = 0; foreach(DeviceInfo& subinfo, devices) { if(subinfo.type == type) { - if(skip_display && subinfo.display_device) { - num_skipped++; + if(subinfo.display_device) { + if(with_display) + num_display++; + else + continue; } - else { - string key = subinfo.description; - if(dupli_map.find(key) == dupli_map.end()) - dupli_map[key] = 1; - else - dupli_map[key]++; + string key = subinfo.description; - info.multi_devices.push_back(subinfo); - if(subinfo.display_device) - info.display_device = true; - num_added++; - } + if(dupli_map.find(key) == dupli_map.end()) + dupli_map[key] = 1; + else + dupli_map[key]++; + + info.multi_devices.push_back(subinfo); + if(subinfo.display_device) + info.display_device = true; + num_added++; } } - if(num_added <= 1 || (skip_display && num_skipped == 0)) + if(num_added <= 1 || (with_display && num_display == 0)) return; /* generate string */ @@ -410,20 +415,24 @@ static void device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool info.type = DEVICE_MULTI; info.description = desc.str(); info.id = string_printf(id_fmt, num); + info.display_device = with_display; info.num = 0; - devices.push_back(info); + if(with_display) + devices.push_back(info); + else + devices.insert(devices.begin(), info); } void device_multi_info(vector<DeviceInfo>& devices) { int num = 0; - device_multi_add(devices, DEVICE_CUDA, true, "CUDA_MULTI_%d", num++); device_multi_add(devices, DEVICE_CUDA, false, "CUDA_MULTI_%d", num++); + device_multi_add(devices, DEVICE_CUDA, true, "CUDA_MULTI_%d", num++); num = 0; - device_multi_add(devices, DEVICE_OPENCL, true, "OPENCL_MULTI_%d", num++); device_multi_add(devices, DEVICE_OPENCL, false, "OPENCL_MULTI_%d", num++); + device_multi_add(devices, DEVICE_OPENCL, true, "OPENCL_MULTI_%d", num++); } CCL_NAMESPACE_END diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp index 4347d7eecd8..14518b1507e 100644 --- a/intern/cycles/device/device_network.cpp +++ b/intern/cycles/device/device_network.cpp @@ -103,7 +103,7 @@ public: #endif } - void mem_copy_from(device_memory& mem, size_t offset, size_t size) + void mem_copy_from(device_memory& mem, int y, int w, int h, int elem) { #if 0 RPCSend snd(socket, "mem_copy_from"); diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp index 41844d37f50..ccfd8544362 100644 --- a/intern/cycles/device/device_opencl.cpp +++ b/intern/cycles/device/device_opencl.cpp @@ -489,8 +489,11 @@ public: opencl_assert(ciErr); } - void mem_copy_from(device_memory& mem, size_t offset, size_t size) + void mem_copy_from(device_memory& mem, int y, int w, int h, int elem) { + size_t offset = elem*y*w; + size_t size = elem*w*h; + ciErr = clEnqueueReadBuffer(cqCommandQueue, CL_MEM_PTR(mem.device_pointer), CL_TRUE, offset, size, (uchar*)mem.data_pointer + offset, 0, NULL, NULL); opencl_assert(ciErr); } @@ -745,6 +748,8 @@ void device_opencl_info(vector<DeviceInfo>& devices) info.description = string(name); info.id = string_printf("OPENCL_%d", num); info.num = num; + /* we don't know if it's used for display, but assume it is */ + info.display_device = true; devices.push_back(info); } diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index dd78ccd8f32..a6bbbc91901 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -87,7 +87,7 @@ float4 *RenderBuffers::copy_from_device(float exposure, int sample) if(!buffer.device_pointer) return NULL; - device->mem_copy_from(buffer, 0, buffer.memory_size()); + device->mem_copy_from(buffer, 0, params.width, params.height, sizeof(float4)); float4 *out = new float4[params.width*params.height]; float4 *in = (float4*)buffer.data_pointer; diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp index f0ddf4e8d7b..c4f3e43bfba 100644 --- a/intern/cycles/render/mesh_displace.cpp +++ b/intern/cycles/render/mesh_displace.cpp @@ -106,7 +106,7 @@ bool MeshManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress& p device->task_add(task); device->task_wait(); - device->mem_copy_from(d_output, 0, sizeof(float3)*d_output.size()); + device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float3)); device->mem_free(d_input); device->mem_free(d_output); diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 046026a3b6e..544fc92e8a4 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -388,13 +388,9 @@ class USERPREF_PT_system(Panel): col.prop(system, "dpi") col.prop(system, "frame_server_port") col.prop(system, "scrollback", text="Console Scrollback") - col.prop(system, "author", text="Author") - col.prop(system, "use_scripts_auto_execute") - col.prop(system, "use_tabs_as_spaces") col.separator() col.separator() - col.separator() col.label(text="Sound:") col.row().prop(system, "audio_device", expand=True) @@ -408,14 +404,20 @@ class USERPREF_PT_system(Panel): col.separator() col.separator() - col.separator() col.label(text="Screencast:") col.prop(system, "screencast_fps") col.prop(system, "screencast_wait_time") + col.separator() col.separator() - col.separator() + + if hasattr(system, 'compute_device'): + col.label(text="Compute Device:") + col.row().prop(system, "compute_device_type", expand=True) + sub = col.row() + sub.active = system.compute_device_type != 'CPU' + sub.prop(system, "compute_device", text="") # 2. Column column = split.column() @@ -727,6 +729,7 @@ class USERPREF_PT_file(Panel): userpref = context.user_preferences paths = userpref.filepaths + system = userpref.system split = layout.split(percentage=0.7) @@ -762,6 +765,14 @@ class USERPREF_PT_file(Panel): subsplit.prop(paths, "animation_player_preset", text="") subsplit.prop(paths, "animation_player", text="") + col.separator() + col.separator() + + colsplit = col.split(percentage=0.95) + sub = colsplit.column() + sub.label(text="Author:") + sub.prop(system, "author", text="") + col = split.column() col.label(text="Save & Load:") col.prop(paths, "use_relative_paths") @@ -784,6 +795,13 @@ class USERPREF_PT_file(Panel): sub.active = paths.use_auto_save_temporary_files sub.prop(paths, "auto_save_time", text="Timer (mins)") + col.separator() + + col.label(text="Scripts:") + col.prop(system, "use_scripts_auto_execute") + col.prop(system, "use_tabs_as_spaces") + + from .space_userpref_keymap import InputKeyMapPanel diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index b3398460500..fc418069c5c 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -413,6 +413,9 @@ typedef struct UserDef { short pad3; char author[80]; /* author name for file formats supporting it */ + + int compute_device_type; + int compute_device_id; } UserDef; extern UserDef U; /* from blenkernel blender.c */ @@ -627,6 +630,10 @@ extern UserDef U; /* from blenkernel blender.c */ #define NDOF_PANY_INVERT_AXIS (1 << 13) #define NDOF_PANZ_INVERT_AXIS (1 << 14) +/* compute_device_type */ +#define USER_COMPUTE_DEVICE_NONE 0 +#define USER_COMPUTE_DEVICE_OPENCL 1 +#define USER_COMPUTE_DEVICE_CUDA 2 #ifdef __cplusplus } diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 9eea6d83cb9..7eb5d042dd7 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -8,7 +8,7 @@ objs += o incs = '#/intern/guardedalloc #/intern/memutil #/intern/audaspace/intern ../blenkernel ../blenlib ../makesdna intern .' incs += ' ../windowmanager ../editors/include ../gpu ../imbuf ../ikplugin ../blenfont ../blenloader' -incs += ' ../render/extern/include' +incs += ' ../render/extern/include #/intern/cycles/blender' incs += ' ../nodes' incs += ' #/extern/glew/include' @@ -58,6 +58,9 @@ if env['WITH_BF_COLLADA']: if env['WITH_BF_OCEANSIM']: defs.append('WITH_OCEANSIM') +if env['WITH_BF_CYCLES']: + defs.append('WITH_CYCLES') + if env['OURPLATFORM'] == 'linux': cflags='-pthread' incs += ' ../../../extern/binreloc/include' diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index fd9cd26cbfa..5bbdac646a7 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -143,6 +143,9 @@ set(INC_SYS ) +if(WITH_CYCLES) + add_definitions(-DWITH_CYCLES) +endif() if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) @@ -246,6 +249,7 @@ blender_include_dirs( ../../editors/include ../../render/extern/include ../../../../intern/audaspace/intern + ../../../../intern/cycles/blender ../../../../intern/guardedalloc ../../../../intern/memutil ) diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index d710dd06a17..1fc6ed0f130 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -33,7 +33,7 @@ incs = '#/intern/guardedalloc ../../blenlib ../../blenkernel ../../blenloader' incs += ' ../../imbuf ../../makesdna ../../makesrna ../../ikplugin' incs += ' ../../windowmanager ../../editors/include ../../blenfont' incs += ' ../../render/extern/include' -incs += ' #/intern/audaspace/intern ' +incs += ' #/intern/audaspace/intern #/intern/cycles/blender' incs += ' #/extern/glew/include ' if env['WITH_BF_OPENEXR']: @@ -91,6 +91,9 @@ if env['WITH_BF_PYTHON']: if env['WITH_BF_COLLADA']: defs.append('WITH_COLLADA') +if env['WITH_BF_CYCLES']: + defs.append('WITH_CYCLES') + if env['OURPLATFORM'] == 'linux': cflags='-pthread' incs += ' ../../../extern/binreloc/include' diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 164f8e4f0d0..4564b9f2946 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -46,6 +46,14 @@ #include "BKE_sound.h" +#ifdef WITH_CYCLES +static EnumPropertyItem compute_device_type_items[] = { + {USER_COMPUTE_DEVICE_NONE, "NONE", 0, "None", "Don't use compute device"}, + {USER_COMPUTE_DEVICE_CUDA, "CUDA", 0, "CUDA", "Use CUDA for GPU acceleration"}, + {USER_COMPUTE_DEVICE_OPENCL, "OPENCL", 0, "OpenCL", "Use OpenCL for GPU acceleration"}, + { 0, NULL, 0, NULL, NULL}}; +#endif + #ifdef RNA_RUNTIME #include "DNA_object_types.h" @@ -65,6 +73,8 @@ #include "UI_interface.h" +#include "CCL_api.h" + static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { WM_main_add_notifier(NC_WINDOW, NULL); @@ -302,6 +312,68 @@ static void rna_userdef_text_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P WM_main_add_notifier(NC_WINDOW, NULL); } +#ifdef WITH_CYCLES +static EnumPropertyItem *rna_userdef_compute_device_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) +{ + EnumPropertyItem *item= NULL; + int totitem= 0; + + /* add supported device types */ + RNA_enum_items_add_value(&item, &totitem, compute_device_type_items, USER_COMPUTE_DEVICE_NONE); + if(CCL_compute_device_list(0)) + RNA_enum_items_add_value(&item, &totitem, compute_device_type_items, USER_COMPUTE_DEVICE_CUDA); + if(CCL_compute_device_list(1)) + RNA_enum_items_add_value(&item, &totitem, compute_device_type_items, USER_COMPUTE_DEVICE_OPENCL); + + RNA_enum_item_end(&item, &totitem); + *free = 1; + + return item; +} + +static int rna_userdef_compute_device_get(PointerRNA *UNUSED(ptr)) +{ + if(U.compute_device_type == USER_COMPUTE_DEVICE_NONE) + return 0; + + return U.compute_device_id; +} + +static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) +{ + EnumPropertyItem tmp= {0, "", 0, "", ""}; + EnumPropertyItem *item= NULL; + int totitem= 0; + + if(U.compute_device_type == USER_COMPUTE_DEVICE_NONE) { + /* only add a single CPU device */ + tmp.value = 0; + tmp.name = "CPU"; + tmp.identifier = "CPU"; + RNA_enum_item_add(&item, &totitem, &tmp); + } + else { + /* get device list from cycles. it would be good to make this generic + once we have more subsystems using opencl, for now this is easiest */ + int opencl = (U.compute_device_type == USER_COMPUTE_DEVICE_OPENCL); + CCLDeviceInfo *devices = CCL_compute_device_list(opencl); + int a; + + for(a = 0; devices[a].name; a++) { + tmp.value = devices[a].value; + tmp.identifier = devices[a].identifier; + tmp.name = devices[a].name; + RNA_enum_item_add(&item, &totitem, &tmp); + } + } + + RNA_enum_item_end(&item, &totitem); + *free = 1; + + return item; +} +#endif + #else static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna) @@ -2645,6 +2717,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) {18, "UKRAINIAN", 0, "Ukrainian (Український)", "uk_UA"}, { 0, NULL, 0, NULL, NULL}}; +#ifdef WITH_CYCLES + static EnumPropertyItem compute_device_items[] = { + {0, "CPU", 0, "CPU", ""}, + { 0, NULL, 0, NULL, NULL}}; +#endif + srna= RNA_def_struct(brna, "UserPreferencesSystem", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -2853,14 +2931,20 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased"); RNA_def_property_update(prop, 0, "rna_userdef_text_update"); -#if 0 - prop= RNA_def_property(srna, "verse_master", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "versemaster"); - RNA_def_property_ui_text(prop, "Verse Master", "Verse Master-server IP"); - - prop= RNA_def_property(srna, "verse_username", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "verseuser"); - RNA_def_property_ui_text(prop, "Verse Username", "Verse user name"); +#ifdef WITH_CYCLES + prop= RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE); + RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); + RNA_def_property_enum_sdna(prop, NULL, "compute_device_type"); + RNA_def_property_enum_items(prop, compute_device_type_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_userdef_compute_device_type_itemf"); + RNA_def_property_ui_text(prop, "Compute Device Type", "Device to use for computation (rendering with Cycles)"); + + prop= RNA_def_property(srna, "compute_device", PROP_ENUM, PROP_NONE); + RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); + RNA_def_property_enum_sdna(prop, NULL, "compute_device_id"); + RNA_def_property_enum_items(prop, compute_device_items); + RNA_def_property_enum_funcs(prop, "rna_userdef_compute_device_get", NULL, "rna_userdef_compute_device_itemf"); + RNA_def_property_ui_text(prop, "Compute Device", "Device to use for computation"); #endif } diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index cd1666d0eed..2a47c2dcb96 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -6,7 +6,7 @@ Import ('env') incs = '. ../editors/include ../makesdna ../makesrna ../blenfont ../blenlib ../blenkernel ../nodes' incs += ' ../imbuf ../blenloader ../gpu ../render/extern/include ../windowmanager' -incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include' +incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include #intern/cycles/blender' incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC'] is_debug = (env['OURPLATFORM'] in ('win32-mingw', 'win32-vc','win64-vc') and env['BF_DEBUG']) diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index f110576a297..05583e133dc 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -35,6 +35,7 @@ set(INC ../../windowmanager ../../gpu ../../../../intern/guardedalloc + ../../../../intern/cycles/blender ) set(INC_SYS diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 7d91438e4f7..6c961d8e6a8 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -57,12 +57,13 @@ #include "BLI_string_utf8.h" #include "BLI_utildefines.h" - #include "BKE_context.h" #include "BKE_text.h" #include "BKE_main.h" #include "BKE_global.h" /* only for script checking */ +#include "CCL_api.h" + #include "BPY_extern.h" #include "../generic/bpy_internal_import.h" // our own imports @@ -176,8 +177,14 @@ void BPY_context_set(bContext *C) /* defined in AUD_C-API.cpp */ extern PyObject *AUD_initPython(void); -/* defined in cycles/blender */ -extern PyObject *CYCLES_initPython(void); + +#ifdef WITH_CYCLES +/* defined in cycles module */ +static PyObject *CCL_initPython(void) +{ + return (PyObject*)CCL_python_module_init(); +} +#endif static struct _inittab bpy_internal_modules[] = { {(char *)"mathutils", PyInit_mathutils}, @@ -189,7 +196,7 @@ static struct _inittab bpy_internal_modules[] = { {(char *)"aud", AUD_initPython}, #endif #ifdef WITH_CYCLES - {(char *)"_cycles", CYCLES_initPython}, + {(char *)"_cycles", CCL_initPython}, #endif {(char *)"gpu", GPU_initPython}, {NULL, NULL} diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 75d1f182189..9efb8114cbd 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -475,6 +475,9 @@ struct DualConMesh *dualcon(const struct DualConMesh *input_mesh, float scale, int depth) {return 0;} +/* intern/cycles */ +struct CCLDeviceInfo; +struct CCLDeviceInfo *CCL_compute_device_list(int opencl) { return NULL; } char blender_path[] = ""; |