Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / device / device.cpp
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 #include <stdlib.h>
18 #include <string.h>
19
20 #include "device/device.h"
21 #include "device/device_intern.h"
22
23 #include "util/util_debug.h"
24 #include "util/util_foreach.h"
25 #include "util/util_half.h"
26 #include "util/util_logging.h"
27 #include "util/util_math.h"
28 #include "util/util_opengl.h"
29 #include "util/util_time.h"
30 #include "util/util_system.h"
31 #include "util/util_types.h"
32 #include "util/util_vector.h"
33 #include "util/util_string.h"
34
35 CCL_NAMESPACE_BEGIN
36
37 bool Device::need_types_update = true;
38 bool Device::need_devices_update = true;
39 thread_mutex Device::device_mutex;
40 vector<DeviceType> Device::types;
41 vector<DeviceInfo> Device::devices;
42
43 /* Device Requested Features */
44
45 std::ostream& operator <<(std::ostream &os,
46                           const DeviceRequestedFeatures& requested_features)
47 {
48         os << "Experimental features: "
49            << (requested_features.experimental ? "On" : "Off") << std::endl;
50         os << "Max closure count: " << requested_features.max_closure << std::endl;
51         os << "Max nodes group: " << requested_features.max_nodes_group << std::endl;
52         /* TODO(sergey): Decode bitflag into list of names. */
53         os << "Nodes features: " << requested_features.nodes_features << std::endl;
54         os << "Use Hair: "
55            << string_from_bool(requested_features.use_hair) << std::endl;
56         os << "Use Object Motion: "
57            << string_from_bool(requested_features.use_object_motion) << std::endl;
58         os << "Use Camera Motion: "
59            << string_from_bool(requested_features.use_camera_motion) << std::endl;
60         os << "Use Baking: "
61            << string_from_bool(requested_features.use_baking) << std::endl;
62         os << "Use Subsurface: "
63            << string_from_bool(requested_features.use_subsurface) << std::endl;
64         os << "Use Volume: "
65            << string_from_bool(requested_features.use_volume) << std::endl;
66         os << "Use Branched Integrator: "
67            << string_from_bool(requested_features.use_integrator_branched) << std::endl;
68         os << "Use Patch Evaluation: "
69            << string_from_bool(requested_features.use_patch_evaluation) << std::endl;
70         os << "Use Transparent Shadows: "
71            << string_from_bool(requested_features.use_transparent) << std::endl;
72         os << "Use Principled BSDF: "
73            << string_from_bool(requested_features.use_principled) << std::endl;
74         os << "Use Denoising: "
75            << string_from_bool(requested_features.use_denoising) << std::endl;
76         return os;
77 }
78
79 /* Device */
80
81 Device::~Device()
82 {
83         if(!background) {
84                 if(vertex_buffer != 0) {
85                         glDeleteBuffers(1, &vertex_buffer);
86                 }
87                 if(fallback_shader_program != 0) {
88                         glDeleteProgram(fallback_shader_program);
89                 }
90         }
91 }
92
93 /* TODO move shaders to standalone .glsl file. */
94 const char *FALLBACK_VERTEX_SHADER =
95 "#version 330\n"
96 "uniform vec2 fullscreen;\n"
97 "in vec2 texCoord;\n"
98 "in vec2 pos;\n"
99 "out vec2 texCoord_interp;\n"
100 "\n"
101 "vec2 normalize_coordinates()\n"
102 "{\n"
103 "       return (vec2(2.0) * (pos / fullscreen)) - vec2(1.0);\n"
104 "}\n"
105 "\n"
106 "void main()\n"
107 "{\n"
108 "       gl_Position = vec4(normalize_coordinates(), 0.0, 1.0);\n"
109 "       texCoord_interp = texCoord;\n"
110 "}\n\0";
111
112 const char *FALLBACK_FRAGMENT_SHADER =
113 "#version 330\n"
114 "uniform sampler2D image_texture;\n"
115 "in vec2 texCoord_interp;\n"
116 "out vec4 fragColor;\n"
117 "\n"
118 "void main()\n"
119 "{\n"
120 "       fragColor = texture(image_texture, texCoord_interp);\n"
121 "}\n\0";
122
123 static void shader_print_errors(const char *task, const char *log, const char *code)
124 {
125         LOG(ERROR) << "Shader: " << task << " error:";
126         LOG(ERROR) << "===== shader string ====";
127
128         stringstream stream(code);
129         string partial;
130
131         int line = 1;
132         while(getline(stream, partial, '\n')) {
133                 if(line < 10) {
134                         LOG(ERROR) << " " << line << " " << partial;
135                 }
136                 else {
137                         LOG(ERROR) << line << " " << partial;
138                 }
139                 line++;
140         }
141         LOG(ERROR) << log;
142 }
143
144 static int bind_fallback_shader(void)
145 {
146         GLint status;
147         GLchar log[5000];
148         GLsizei length = 0;
149         GLuint program = 0;
150
151         struct Shader {
152                 const char *source;
153                 GLenum type;
154         } shaders[2] = {
155             {FALLBACK_VERTEX_SHADER, GL_VERTEX_SHADER},
156             {FALLBACK_FRAGMENT_SHADER, GL_FRAGMENT_SHADER}
157     };
158
159         program = glCreateProgram();
160
161         for(int i = 0; i < 2; i++) {
162                 GLuint shader = glCreateShader(shaders[i].type);
163
164                 string source_str = shaders[i].source;
165                 const char *c_str = source_str.c_str();
166
167                 glShaderSource(shader, 1, &c_str, NULL);
168                 glCompileShader(shader);
169
170                 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
171
172                 if(!status) {
173                         glGetShaderInfoLog(shader, sizeof(log), &length, log);
174                         shader_print_errors("compile", log, c_str);
175                         return 0;
176                 }
177
178                 glAttachShader(program, shader);
179         }
180
181         /* Link output. */
182         glBindFragDataLocation(program, 0, "fragColor");
183
184         /* Link and error check. */
185         glLinkProgram(program);
186
187         glGetProgramiv(program, GL_LINK_STATUS, &status);
188         if(!status) {
189                 glGetShaderInfoLog(program, sizeof(log), &length, log);
190                 shader_print_errors("linking", log, FALLBACK_VERTEX_SHADER);
191                 shader_print_errors("linking", log, FALLBACK_FRAGMENT_SHADER);
192                 return 0;
193         }
194
195         return program;
196 }
197
198 bool Device::bind_fallback_display_space_shader(const float width, const float height)
199 {
200         if(fallback_status == FALLBACK_SHADER_STATUS_ERROR) {
201                 return false;
202         }
203
204         if(fallback_status == FALLBACK_SHADER_STATUS_NONE) {
205                 fallback_shader_program = bind_fallback_shader();
206                 fallback_status = FALLBACK_SHADER_STATUS_ERROR;
207
208                 if (fallback_shader_program == 0) {
209                         return false;
210                 }
211
212                 glUseProgram(fallback_shader_program);
213                 image_texture_location = glGetUniformLocation(fallback_shader_program, "image_texture");
214                 if(image_texture_location < 0) {
215                         LOG(ERROR) << "Shader doesn't containt the 'image_texture' uniform.";
216                         return false;
217                 }
218
219                 fullscreen_location = glGetUniformLocation(fallback_shader_program, "fullscreen");
220                 if(fullscreen_location < 0) {
221                         LOG(ERROR) << "Shader doesn't containt the 'fullscreen' uniform.";
222                         return false;
223                 }
224
225                 fallback_status = FALLBACK_SHADER_STATUS_SUCCESS;
226         }
227
228         /* Run this every time. */
229         glUseProgram(fallback_shader_program);
230         glUniform1i(image_texture_location, 0);
231         glUniform2f(fullscreen_location, width, height);
232         return true;
233 }
234
235 void Device::draw_pixels(
236     device_memory& rgba, int y,
237     int w, int h, int width, int height,
238     int dx, int dy, int dw, int dh,
239     bool transparent, const DeviceDrawParams &draw_params)
240 {
241         const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL);
242
243         assert(rgba.type == MEM_PIXELS);
244         mem_copy_from(rgba, y, w, h, rgba.memory_elements_size(1));
245
246         GLuint texid;
247         glGenTextures(1, &texid);
248         glBindTexture(GL_TEXTURE_2D, texid);
249
250         if(rgba.data_type == TYPE_HALF) {
251                 GLhalf *data_pointer = (GLhalf*)rgba.host_pointer;
252                 data_pointer += 4 * y * w;
253                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, w, h, 0, GL_RGBA, GL_HALF_FLOAT, data_pointer);
254         }
255         else {
256                 uint8_t *data_pointer = (uint8_t*)rgba.host_pointer;
257                 data_pointer += 4 * y * w;
258                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_pointer);
259         }
260
261         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
262         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
263
264         glEnable(GL_TEXTURE_2D);
265
266         if(transparent) {
267                 glEnable(GL_BLEND);
268                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
269         }
270
271         GLint shader_program;
272         if(use_fallback_shader) {
273                 if (!bind_fallback_display_space_shader(dw, dh)) {
274                         return;
275                 }
276                 shader_program = fallback_shader_program;
277         }
278         else {
279                 draw_params.bind_display_space_shader_cb();
280                 glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program);
281         }
282
283         if(!vertex_buffer) {
284                 glGenBuffers(1, &vertex_buffer);
285         }
286
287         glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
288         /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
289         glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
290
291         float *vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
292
293         if(vpointer) {
294                 /* texture coordinate - vertex pair */
295                 vpointer[0] = 0.0f;
296                 vpointer[1] = 0.0f;
297                 vpointer[2] = dx;
298                 vpointer[3] = dy;
299
300                 vpointer[4] = 1.0f;
301                 vpointer[5] = 0.0f;
302                 vpointer[6] = (float)width + dx;
303                 vpointer[7] = dy;
304
305                 vpointer[8] = 1.0f;
306                 vpointer[9] = 1.0f;
307                 vpointer[10] = (float)width + dx;
308                 vpointer[11] = (float)height + dy;
309
310                 vpointer[12] = 0.0f;
311                 vpointer[13] = 1.0f;
312                 vpointer[14] = dx;
313                 vpointer[15] = (float)height + dy;
314
315                 if(vertex_buffer) {
316                         glUnmapBuffer(GL_ARRAY_BUFFER);
317                 }
318         }
319
320         GLuint vertex_array_object;
321         GLuint position_attribute, texcoord_attribute;
322
323         glGenVertexArrays(1, &vertex_array_object);
324         glBindVertexArray(vertex_array_object);
325
326         texcoord_attribute = glGetAttribLocation(shader_program, "texCoord");
327         position_attribute = glGetAttribLocation(shader_program, "pos");
328
329         glEnableVertexAttribArray(texcoord_attribute);
330         glEnableVertexAttribArray(position_attribute);
331
332         glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
333         glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)(sizeof(float) * 2));
334
335         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
336
337         if(vertex_buffer) {
338                 glBindBuffer(GL_ARRAY_BUFFER, 0);
339         }
340
341         if(use_fallback_shader) {
342                 glUseProgram(0);
343         }
344         else {
345                 draw_params.unbind_display_space_shader_cb();
346         }
347
348         glBindTexture(GL_TEXTURE_2D, 0);
349         glDisable(GL_TEXTURE_2D);
350         glDeleteTextures(1, &texid);
351
352         if(transparent) {
353                 glDisable(GL_BLEND);
354         }
355 }
356
357 Device *Device::create(DeviceInfo& info, Stats &stats, bool background)
358 {
359         Device *device;
360
361         switch(info.type) {
362                 case DEVICE_CPU:
363                         device = device_cpu_create(info, stats, background);
364                         break;
365 #ifdef WITH_CUDA
366                 case DEVICE_CUDA:
367                         if(device_cuda_init())
368                                 device = device_cuda_create(info, stats, background);
369                         else
370                                 device = NULL;
371                         break;
372 #endif
373 #ifdef WITH_MULTI
374                 case DEVICE_MULTI:
375                         device = device_multi_create(info, stats, background);
376                         break;
377 #endif
378 #ifdef WITH_NETWORK
379                 case DEVICE_NETWORK:
380                         device = device_network_create(info, stats, "127.0.0.1");
381                         break;
382 #endif
383 #ifdef WITH_OPENCL
384                 case DEVICE_OPENCL:
385                         if(device_opencl_init())
386                                 device = device_opencl_create(info, stats, background);
387                         else
388                                 device = NULL;
389                         break;
390 #endif
391                 default:
392                         return NULL;
393         }
394
395         return device;
396 }
397
398 DeviceType Device::type_from_string(const char *name)
399 {
400         if(strcmp(name, "CPU") == 0)
401                 return DEVICE_CPU;
402         else if(strcmp(name, "CUDA") == 0)
403                 return DEVICE_CUDA;
404         else if(strcmp(name, "OPENCL") == 0)
405                 return DEVICE_OPENCL;
406         else if(strcmp(name, "NETWORK") == 0)
407                 return DEVICE_NETWORK;
408         else if(strcmp(name, "MULTI") == 0)
409                 return DEVICE_MULTI;
410
411         return DEVICE_NONE;
412 }
413
414 string Device::string_from_type(DeviceType type)
415 {
416         if(type == DEVICE_CPU)
417                 return "CPU";
418         else if(type == DEVICE_CUDA)
419                 return "CUDA";
420         else if(type == DEVICE_OPENCL)
421                 return "OPENCL";
422         else if(type == DEVICE_NETWORK)
423                 return "NETWORK";
424         else if(type == DEVICE_MULTI)
425                 return "MULTI";
426
427         return "";
428 }
429
430 vector<DeviceType>& Device::available_types()
431 {
432         thread_scoped_lock lock(device_mutex);
433         if(need_types_update) {
434                 types.clear();
435                 types.push_back(DEVICE_CPU);
436 #ifdef WITH_CUDA
437                 if(device_cuda_init()) {
438                         types.push_back(DEVICE_CUDA);
439                 }
440 #endif
441 #ifdef WITH_OPENCL
442                 if(device_opencl_init()) {
443                         types.push_back(DEVICE_OPENCL);
444                 }
445 #endif
446 #ifdef WITH_NETWORK
447                 types.push_back(DEVICE_NETWORK);
448 #endif
449                 need_types_update = false;
450         }
451         return types;
452 }
453
454 vector<DeviceInfo>& Device::available_devices()
455 {
456         thread_scoped_lock lock(device_mutex);
457         if(need_devices_update) {
458                 devices.clear();
459 #ifdef WITH_OPENCL
460                 if(device_opencl_init()) {
461                         device_opencl_info(devices);
462                 }
463 #endif
464 #ifdef WITH_CUDA
465                 if(device_cuda_init()) {
466                         device_cuda_info(devices);
467                 }
468 #endif
469                 device_cpu_info(devices);
470 #ifdef WITH_NETWORK
471                 device_network_info(devices);
472 #endif
473                 need_devices_update = false;
474         }
475         return devices;
476 }
477
478 string Device::device_capabilities()
479 {
480         string capabilities = "CPU device capabilities: ";
481         capabilities += device_cpu_capabilities() + "\n";
482
483 #ifdef WITH_OPENCL
484         if(device_opencl_init()) {
485                 capabilities += "\nOpenCL device capabilities:\n";
486                 capabilities += device_opencl_capabilities();
487         }
488 #endif
489
490 #ifdef WITH_CUDA
491         if(device_cuda_init()) {
492                 capabilities += "\nCUDA device capabilities:\n";
493                 capabilities += device_cuda_capabilities();
494         }
495 #endif
496
497         return capabilities;
498 }
499
500 DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int threads, bool background)
501 {
502         assert(subdevices.size() > 1);
503
504         DeviceInfo info;
505         info.type = DEVICE_MULTI;
506         info.id = "MULTI";
507         info.description = "Multi Device";
508         info.num = 0;
509
510         info.has_fermi_limits = false;
511         info.has_half_images = true;
512         info.has_volume_decoupled = true;
513         info.has_qbvh = true;
514         info.has_osl = true;
515
516         foreach(const DeviceInfo &device, subdevices) {
517                 /* Ensure CPU device does not slow down GPU. */
518                 if(device.type == DEVICE_CPU && subdevices.size() > 1) {
519                         if(background) {
520                                 int orig_cpu_threads = (threads)? threads: system_cpu_thread_count();
521                                 int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
522
523                                 VLOG(1) << "CPU render threads reduced from "
524                                                 << orig_cpu_threads << " to " << cpu_threads
525                                                 << ", to dedicate to GPU.";
526
527                                 if(cpu_threads >= 1) {
528                                         DeviceInfo cpu_device = device;
529                                         cpu_device.cpu_threads = cpu_threads;
530                                         info.multi_devices.push_back(cpu_device);
531                                 }
532                                 else {
533                                         continue;
534                                 }
535                         }
536                         else {
537                                 VLOG(1) << "CPU render threads disabled for interactive render.";
538                                 continue;
539                         }
540                 }
541                 else {
542                         info.multi_devices.push_back(device);
543                 }
544
545                 /* Accumulate device info. */
546                 info.has_fermi_limits = info.has_fermi_limits ||
547                                         device.has_fermi_limits;
548                 info.has_half_images &= device.has_half_images;
549                 info.has_volume_decoupled &= device.has_volume_decoupled;
550                 info.has_qbvh &= device.has_qbvh;
551                 info.has_osl &= device.has_osl;
552         }
553
554         return info;
555 }
556
557 void Device::tag_update()
558 {
559         need_types_update = true;
560         need_devices_update = true;
561 }
562
563 void Device::free_memory()
564 {
565         need_types_update = true;
566         need_devices_update = true;
567         types.free_memory();
568         devices.free_memory();
569 }
570
571 CCL_NAMESPACE_END