Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/CCL_api.h46
-rw-r--r--intern/cycles/blender/CMakeLists.txt1
-rw-r--r--intern/cycles/blender/addon/engine.py3
-rw-r--r--intern/cycles/blender/addon/enums.py24
-rw-r--r--intern/cycles/blender/addon/properties.py3
-rw-r--r--intern/cycles/blender/addon/ui.py16
-rw-r--r--intern/cycles/blender/blender_python.cpp73
-rw-r--r--intern/cycles/blender/blender_session.cpp19
-rw-r--r--intern/cycles/blender/blender_session.h7
-rw-r--r--intern/cycles/blender/blender_sync.cpp50
-rw-r--r--intern/cycles/blender/blender_sync.h2
-rw-r--r--intern/cycles/device/device.cpp2
-rw-r--r--intern/cycles/device/device.h2
-rw-r--r--intern/cycles/device/device_cpu.cpp2
-rw-r--r--intern/cycles/device/device_cuda.cpp19
-rw-r--r--intern/cycles/device/device_multi.cpp55
-rw-r--r--intern/cycles/device/device_network.cpp2
-rw-r--r--intern/cycles/device/device_opencl.cpp7
-rw-r--r--intern/cycles/render/buffers.cpp2
-rw-r--r--intern/cycles/render/mesh_displace.cpp2
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py30
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h7
-rw-r--r--source/blender/makesrna/SConscript5
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt4
-rw-r--r--source/blender/makesrna/intern/SConscript5
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c100
-rw-r--r--source/blender/python/SConscript2
-rw-r--r--source/blender/python/intern/CMakeLists.txt1
-rw-r--r--source/blender/python/intern/bpy_interface.c15
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c3
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[] = "";