Merge branch 'blender2.7'
[blender.git] / intern / cycles / device / device.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __DEVICE_H__
18 #define __DEVICE_H__
19
20 #include <stdlib.h>
21
22 #include "bvh/bvh_params.h"
23
24 #include "device/device_memory.h"
25 #include "device/device_task.h"
26
27 #include "util/util_list.h"
28 #include "util/util_stats.h"
29 #include "util/util_string.h"
30 #include "util/util_thread.h"
31 #include "util/util_texture.h"
32 #include "util/util_types.h"
33 #include "util/util_vector.h"
34
35 CCL_NAMESPACE_BEGIN
36
37 class Progress;
38 class RenderTile;
39
40 /* Device Types */
41
42 enum DeviceType {
43         DEVICE_NONE = 0,
44         DEVICE_CPU,
45         DEVICE_OPENCL,
46         DEVICE_CUDA,
47         DEVICE_NETWORK,
48         DEVICE_MULTI
49 };
50
51 enum DeviceTypeMask {
52         DEVICE_MASK_CPU = (1 << DEVICE_CPU),
53         DEVICE_MASK_OPENCL = (1 << DEVICE_OPENCL),
54         DEVICE_MASK_CUDA = (1 << DEVICE_CUDA),
55         DEVICE_MASK_NETWORK = (1 << DEVICE_NETWORK),
56         DEVICE_MASK_ALL = ~0
57 };
58
59 #define DEVICE_MASK(type) (DeviceTypeMask)(1 << type)
60
61 class DeviceInfo {
62 public:
63         DeviceType type;
64         string description;
65         string id; /* used for user preferences, should stay fixed with changing hardware config */
66         int num;
67         bool display_device;            /* GPU is used as a display device. */
68         bool advanced_shading;          /* Supports full shading system. */
69         bool has_half_images;           /* Support half-float textures. */
70         bool has_volume_decoupled;      /* Decoupled volume shading. */
71         bool has_osl;                   /* Support Open Shading Language. */
72         bool use_split_kernel;          /* Use split or mega kernel. */
73         bool has_profiling;             /* Supports runtime collection of profiling info. */
74         int cpu_threads;
75         vector<DeviceInfo> multi_devices;
76
77         DeviceInfo()
78         {
79                 type = DEVICE_CPU;
80                 id = "CPU";
81                 num = 0;
82                 cpu_threads = 0;
83                 display_device = false;
84                 advanced_shading = true;
85                 has_half_images = false;
86                 has_volume_decoupled = false;
87                 has_osl = false;
88                 use_split_kernel = false;
89                 has_profiling = false;
90         }
91
92         bool operator==(const DeviceInfo &info) {
93                 /* Multiple Devices with the same ID would be very bad. */
94                 assert(id != info.id || (type == info.type && num == info.num && description == info.description));
95                 return id == info.id;
96         }
97 };
98
99 class DeviceRequestedFeatures {
100 public:
101         /* Use experimental feature set. */
102         bool experimental;
103
104         /* Selective nodes compilation. */
105
106         /* Identifier of a node group up to which all the nodes needs to be
107          * compiled in. Nodes from higher group indices will be ignores.
108          */
109         int max_nodes_group;
110
111         /* Features bitfield indicating which features from the requested group
112          * will be compiled in. Nodes which corresponds to features which are not
113          * in this bitfield will be ignored even if they're in the requested group.
114          */
115         int nodes_features;
116
117         /* BVH/sampling kernel features. */
118         bool use_hair;
119         bool use_object_motion;
120         bool use_camera_motion;
121
122         /* Denotes whether baking functionality is needed. */
123         bool use_baking;
124
125         /* Use subsurface scattering materials. */
126         bool use_subsurface;
127
128         /* Use volume materials. */
129         bool use_volume;
130
131         /* Use branched integrator. */
132         bool use_integrator_branched;
133
134         /* Use OpenSubdiv patch evaluation */
135         bool use_patch_evaluation;
136
137         /* Use Transparent shadows */
138         bool use_transparent;
139
140         /* Use various shadow tricks, such as shadow catcher. */
141         bool use_shadow_tricks;
142
143         /* Per-uber shader usage flags. */
144         bool use_principled;
145
146         /* Denoising features. */
147         bool use_denoising;
148
149         /* Use raytracing in shaders. */
150         bool use_shader_raytrace;
151
152         DeviceRequestedFeatures()
153         {
154                 /* TODO(sergey): Find more meaningful defaults. */
155                 experimental = false;
156                 max_nodes_group = 0;
157                 nodes_features = 0;
158                 use_hair = false;
159                 use_object_motion = false;
160                 use_camera_motion = false;
161                 use_baking = false;
162                 use_subsurface = false;
163                 use_volume = false;
164                 use_integrator_branched = false;
165                 use_patch_evaluation = false;
166                 use_transparent = false;
167                 use_shadow_tricks = false;
168                 use_principled = false;
169                 use_denoising = false;
170                 use_shader_raytrace = false;
171         }
172
173         bool modified(const DeviceRequestedFeatures& requested_features)
174         {
175                 return !(experimental == requested_features.experimental &&
176                          max_nodes_group == requested_features.max_nodes_group &&
177                          nodes_features == requested_features.nodes_features &&
178                          use_hair == requested_features.use_hair &&
179                          use_object_motion == requested_features.use_object_motion &&
180                          use_camera_motion == requested_features.use_camera_motion &&
181                          use_baking == requested_features.use_baking &&
182                          use_subsurface == requested_features.use_subsurface &&
183                          use_volume == requested_features.use_volume &&
184                          use_integrator_branched == requested_features.use_integrator_branched &&
185                          use_patch_evaluation == requested_features.use_patch_evaluation &&
186                          use_transparent == requested_features.use_transparent &&
187                          use_shadow_tricks == requested_features.use_shadow_tricks &&
188                          use_principled == requested_features.use_principled &&
189                          use_denoising == requested_features.use_denoising &&
190                          use_shader_raytrace == requested_features.use_shader_raytrace);
191         }
192
193         /* Convert the requested features structure to a build options,
194          * which could then be passed to compilers.
195          */
196         string get_build_options() const
197         {
198                 string build_options = "";
199                 if(experimental) {
200                         build_options += "-D__KERNEL_EXPERIMENTAL__ ";
201                 }
202                 build_options += "-D__NODES_MAX_GROUP__=" +
203                         string_printf("%d", max_nodes_group);
204                 build_options += " -D__NODES_FEATURES__=" +
205                         string_printf("%d", nodes_features);
206                 if(!use_hair) {
207                         build_options += " -D__NO_HAIR__";
208                 }
209                 if(!use_object_motion) {
210                         build_options += " -D__NO_OBJECT_MOTION__";
211                 }
212                 if(!use_camera_motion) {
213                         build_options += " -D__NO_CAMERA_MOTION__";
214                 }
215                 if(!use_baking) {
216                         build_options += " -D__NO_BAKING__";
217                 }
218                 if(!use_volume) {
219                         build_options += " -D__NO_VOLUME__";
220                 }
221                 if(!use_subsurface) {
222                         build_options += " -D__NO_SUBSURFACE__";
223                 }
224                 if(!use_integrator_branched) {
225                         build_options += " -D__NO_BRANCHED_PATH__";
226                 }
227                 if(!use_patch_evaluation) {
228                         build_options += " -D__NO_PATCH_EVAL__";
229                 }
230                 if(!use_transparent && !use_volume) {
231                         build_options += " -D__NO_TRANSPARENT__";
232                 }
233                 if(!use_shadow_tricks) {
234                         build_options += " -D__NO_SHADOW_TRICKS__";
235                 }
236                 if(!use_principled) {
237                         build_options += " -D__NO_PRINCIPLED__";
238                 }
239                 if(!use_denoising) {
240                         build_options += " -D__NO_DENOISING__";
241                 }
242                 if(!use_shader_raytrace) {
243                         build_options += " -D__NO_SHADER_RAYTRACE__";
244                 }
245                 return build_options;
246         }
247 };
248
249 std::ostream& operator <<(std::ostream &os,
250                           const DeviceRequestedFeatures& requested_features);
251
252 /* Device */
253
254 struct DeviceDrawParams {
255         function<void()> bind_display_space_shader_cb;
256         function<void()> unbind_display_space_shader_cb;
257 };
258
259 class Device {
260         friend class device_sub_ptr;
261 protected:
262         enum {
263                 FALLBACK_SHADER_STATUS_NONE = 0,
264                 FALLBACK_SHADER_STATUS_ERROR,
265                 FALLBACK_SHADER_STATUS_SUCCESS,
266         };
267
268         Device(DeviceInfo& info_, Stats &stats_, Profiler &profiler_, bool background) : background(background),
269             vertex_buffer(0),
270             fallback_status(FALLBACK_SHADER_STATUS_NONE), fallback_shader_program(0),
271             info(info_), stats(stats_), profiler(profiler_) {}
272
273         bool background;
274         string error_msg;
275
276         /* used for real time display */
277         unsigned int vertex_buffer;
278         int fallback_status, fallback_shader_program;
279         int image_texture_location, fullscreen_location;
280
281         bool bind_fallback_display_space_shader(const float width, const float height);
282
283         virtual device_ptr mem_alloc_sub_ptr(device_memory& /*mem*/, int /*offset*/, int /*size*/)
284         {
285                 /* Only required for devices that implement denoising. */
286                 assert(false);
287                 return (device_ptr) 0;
288         }
289         virtual void mem_free_sub_ptr(device_ptr /*ptr*/) {};
290
291 public:
292         virtual ~Device();
293
294         /* info */
295         DeviceInfo info;
296         virtual const string& error_message() { return error_msg; }
297         bool have_error() { return !error_message().empty(); }
298         virtual void set_error(const string& error)
299         {
300                 if(!have_error()) {
301                         error_msg = error;
302                 }
303                 fprintf(stderr, "%s\n", error.c_str());
304                 fflush(stderr);
305         }
306         virtual bool show_samples() const { return false; }
307         virtual BVHLayoutMask get_bvh_layout_mask() const = 0;
308
309         /* statistics */
310         Stats &stats;
311         Profiler &profiler;
312
313         /* memory alignment */
314         virtual int mem_sub_ptr_alignment() { return MIN_ALIGNMENT_CPU_DATA_TYPES; }
315
316         /* constant memory */
317         virtual void const_copy_to(const char *name, void *host, size_t size) = 0;
318
319         /* open shading language, only for CPU device */
320         virtual void *osl_memory() { return NULL; }
321
322         /* load/compile kernels, must be called before adding tasks */
323         virtual bool load_kernels(
324                 const DeviceRequestedFeatures& /*requested_features*/)
325         { return true; }
326
327         /* tasks */
328         virtual int get_split_task_count(DeviceTask& task) = 0;
329         virtual void task_add(DeviceTask& task) = 0;
330         virtual void task_wait() = 0;
331         virtual void task_cancel() = 0;
332
333         /* opengl drawing */
334         virtual void draw_pixels(device_memory& mem, int y,
335             int w, int h, int width, int height,
336             int dx, int dy, int dw, int dh,
337             bool transparent, const DeviceDrawParams &draw_params);
338
339 #ifdef WITH_NETWORK
340         /* networking */
341         void server_run();
342 #endif
343
344         /* multi device */
345         virtual void map_tile(Device * /*sub_device*/, RenderTile& /*tile*/) {}
346         virtual int device_number(Device * /*sub_device*/) { return 0; }
347         virtual void map_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/) {}
348         virtual void unmap_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/) {}
349
350         /* static */
351         static Device *create(DeviceInfo& info, Stats &stats, Profiler& profiler, bool background = true);
352
353         static DeviceType type_from_string(const char *name);
354         static string string_from_type(DeviceType type);
355         static vector<DeviceType> available_types();
356         static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
357         static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
358         static DeviceInfo get_multi_device(const vector<DeviceInfo>& subdevices,
359                                            int threads,
360                                            bool background);
361
362         /* Tag devices lists for update. */
363         static void tag_update();
364
365         static void free_memory();
366
367 protected:
368         /* Memory allocation, only accessed through device_memory. */
369         friend class MultiDevice;
370         friend class DeviceServer;
371         friend class device_memory;
372
373         virtual void mem_alloc(device_memory& mem) = 0;
374         virtual void mem_copy_to(device_memory& mem) = 0;
375         virtual void mem_copy_from(device_memory& mem,
376                 int y, int w, int h, int elem) = 0;
377         virtual void mem_zero(device_memory& mem) = 0;
378         virtual void mem_free(device_memory& mem) = 0;
379
380 private:
381         /* Indicted whether device types and devices lists were initialized. */
382         static bool need_types_update, need_devices_update;
383         static thread_mutex device_mutex;
384         static vector<DeviceInfo> cuda_devices;
385         static vector<DeviceInfo> opencl_devices;
386         static vector<DeviceInfo> cpu_devices;
387         static vector<DeviceInfo> network_devices;
388         static uint devices_initialized_mask;
389 };
390
391 CCL_NAMESPACE_END
392
393 #endif  /* __DEVICE_H__ */