Blender  V3.3
cycles_standalone.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include <stdio.h>
5 
6 #include "device/device.h"
7 #include "scene/camera.h"
8 #include "scene/integrator.h"
9 #include "scene/scene.h"
10 #include "session/buffers.h"
11 #include "session/session.h"
12 
13 #include "util/args.h"
14 #include "util/foreach.h"
15 #include "util/function.h"
16 #include "util/image.h"
17 #include "util/log.h"
18 #include "util/path.h"
19 #include "util/progress.h"
20 #include "util/string.h"
21 #include "util/time.h"
22 #include "util/transform.h"
23 #include "util/unique_ptr.h"
24 #include "util/version.h"
25 
26 #ifdef WITH_USD
27 # include "hydra/file_reader.h"
28 #endif
29 
30 #include "app/cycles_xml.h"
31 #include "app/oiio_output_driver.h"
32 
33 #ifdef WITH_CYCLES_STANDALONE_GUI
34 # include "opengl/display_driver.h"
35 # include "opengl/window.h"
36 #endif
37 
39 
40 struct Options {
43  string filepath;
44  int width, height;
47  bool quiet;
50  string output_pass;
52 
53 static void session_print(const string &str)
54 {
55  /* print with carriage return to overwrite previous */
56  printf("\r%s", str.c_str());
57 
58  /* add spaces to overwrite longer previous print */
59  static int maxlen = 0;
60  int len = str.size();
61  maxlen = max(len, maxlen);
62 
63  for (int i = len; i < maxlen; i++)
64  printf(" ");
65 
66  /* flush because we don't write an end of line */
67  fflush(stdout);
68 }
69 
70 static void session_print_status()
71 {
72  string status, substatus;
73 
74  /* get status */
75  double progress = options.session->progress.get_progress();
76  options.session->progress.get_status(status, substatus);
77 
78  if (substatus != "")
79  status += ": " + substatus;
80 
81  /* print status */
82  status = string_printf("Progress %05.2f %s", (double)progress * 100, status.c_str());
83  session_print(status);
84 }
85 
87 {
88  static BufferParams buffer_params;
89  buffer_params.width = options.width;
90  buffer_params.height = options.height;
91  buffer_params.full_width = options.width;
92  buffer_params.full_height = options.height;
93 
94  return buffer_params;
95 }
96 
97 static void scene_init()
98 {
100 
101  /* Read XML or USD */
102 #ifdef WITH_USD
104  HD_CYCLES_NS::HdCyclesFileReader::read(options.session, options.filepath.c_str());
105  }
106  else
107 #endif
108  {
110  }
111 
112  /* Camera width/height override? */
113  if (!(options.width == 0 || options.height == 0)) {
114  options.scene->camera->set_full_width(options.width);
115  options.scene->camera->set_full_height(options.height);
116  }
117  else {
118  options.width = options.scene->camera->get_full_width();
119  options.height = options.scene->camera->get_full_height();
120  }
121 
122  /* Calculate Viewplane */
123  options.scene->camera->compute_auto_viewplane();
124 }
125 
126 static void session_init()
127 {
128  options.output_pass = "combined";
130 
131 #ifdef WITH_CYCLES_STANDALONE_GUI
133  options.session->set_display_driver(make_unique<OpenGLDisplayDriver>(
135  }
136 #endif
137 
138  if (!options.output_filepath.empty()) {
139  options.session->set_output_driver(make_unique<OIIOOutputDriver>(
141  }
142 
145 #ifdef WITH_CYCLES_STANDALONE_GUI
146  else
148 #endif
149 
150  /* load scene */
151  scene_init();
152 
153  /* add pass for output. */
154  Pass *pass = options.scene->create_node<Pass>();
155  pass->set_name(ustring(options.output_pass.c_str()));
156  pass->set_type(PASS_COMBINED);
157 
159  options.session->start();
160 }
161 
162 static void session_exit()
163 {
164  if (options.session) {
165  delete options.session;
166  options.session = NULL;
167  }
168 
170  session_print("Finished Rendering.");
171  printf("\n");
172  }
173 }
174 
175 #ifdef WITH_CYCLES_STANDALONE_GUI
176 static void display_info(Progress &progress)
177 {
178  static double latency = 0.0;
179  static double last = 0;
180  double elapsed = time_dt();
181  string str, interactive;
182 
183  latency = (elapsed - last);
184  last = elapsed;
185 
186  double total_time, sample_time;
187  string status, substatus;
188 
189  progress.get_time(total_time, sample_time);
190  progress.get_status(status, substatus);
191  double progress_val = progress.get_progress();
192 
193  if (substatus != "")
194  status += ": " + substatus;
195 
196  interactive = options.interactive ? "On" : "Off";
197 
198  str = string_printf(
199  "%s"
200  " Time: %.2f"
201  " Latency: %.4f"
202  " Progress: %05.2f"
203  " Average: %.4f"
204  " Interactive: %s",
205  status.c_str(),
206  total_time,
207  latency,
208  (double)progress_val * 100,
209  sample_time,
210  interactive.c_str());
211 
212  window_display_info(str.c_str());
213 
214  if (options.show_help)
216 }
217 
218 static void display()
219 {
220  options.session->draw();
221 
222  display_info(options.session->progress);
223 }
224 
225 static void motion(int x, int y, int button)
226 {
227  if (options.interactive) {
228  Transform matrix = options.session->scene->camera->get_matrix();
229 
230  /* Translate */
231  if (button == 0) {
232  float3 translate = make_float3(x * 0.01f, -(y * 0.01f), 0.0f);
233  matrix = matrix * transform_translate(translate);
234  }
235 
236  /* Rotate */
237  else if (button == 2) {
238  float4 r1 = make_float4((float)x * 0.1f, 0.0f, 1.0f, 0.0f);
239  matrix = matrix * transform_rotate(DEG2RADF(r1.x), make_float3(r1.y, r1.z, r1.w));
240 
241  float4 r2 = make_float4(y * 0.1f, 1.0f, 0.0f, 0.0f);
242  matrix = matrix * transform_rotate(DEG2RADF(r2.x), make_float3(r2.y, r2.z, r2.w));
243  }
244 
245  /* Update and Reset */
246  options.session->scene->camera->set_matrix(matrix);
247  options.session->scene->camera->need_flags_update = true;
248  options.session->scene->camera->need_device_update = true;
249 
251  }
252 }
253 
254 static void resize(int width, int height)
255 {
256  options.width = width;
258 
259  if (options.session) {
260  /* Update camera */
261  options.session->scene->camera->set_full_width(options.width);
262  options.session->scene->camera->set_full_height(options.height);
263  options.session->scene->camera->compute_auto_viewplane();
264  options.session->scene->camera->need_flags_update = true;
265  options.session->scene->camera->need_device_update = true;
266 
268  }
269 }
270 
271 static void keyboard(unsigned char key)
272 {
273  /* Toggle help */
274  if (key == 'h')
276 
277  /* Reset */
278  else if (key == 'r')
280 
281  /* Cancel */
282  else if (key == 27) // escape
283  options.session->progress.set_cancel("Canceled");
284 
285  /* Pause */
286  else if (key == 'p') {
289  }
290 
291  /* Interactive Mode */
292  else if (key == 'i')
294 
295  /* Navigation */
296  else if (options.interactive && (key == 'w' || key == 'a' || key == 's' || key == 'd')) {
297  Transform matrix = options.session->scene->camera->get_matrix();
298  float3 translate;
299 
300  if (key == 'w')
301  translate = make_float3(0.0f, 0.0f, 0.1f);
302  else if (key == 's')
303  translate = make_float3(0.0f, 0.0f, -0.1f);
304  else if (key == 'a')
305  translate = make_float3(-0.1f, 0.0f, 0.0f);
306  else if (key == 'd')
307  translate = make_float3(0.1f, 0.0f, 0.0f);
308 
309  matrix = matrix * transform_translate(translate);
310 
311  /* Update and Reset */
312  options.session->scene->camera->set_matrix(matrix);
313  options.session->scene->camera->need_flags_update = true;
314  options.session->scene->camera->need_device_update = true;
315 
317  }
318 
319  /* Set Max Bounces */
320  else if (options.interactive && (key == '0' || key == '1' || key == '2' || key == '3')) {
321  int bounce;
322  switch (key) {
323  case '0':
324  bounce = 0;
325  break;
326  case '1':
327  bounce = 1;
328  break;
329  case '2':
330  bounce = 2;
331  break;
332  case '3':
333  bounce = 3;
334  break;
335  default:
336  bounce = 0;
337  break;
338  }
339 
340  options.session->scene->integrator->set_max_bounce(bounce);
341 
343  }
344 }
345 #endif
346 
347 static int files_parse(int argc, const char *argv[])
348 {
349  if (argc > 0)
350  options.filepath = argv[0];
351 
352  return 0;
353 }
354 
355 static void options_parse(int argc, const char **argv)
356 {
357  options.width = 1024;
358  options.height = 512;
359  options.filepath = "";
360  options.session = NULL;
361  options.quiet = false;
364 
365  /* device names */
366  string device_names = "";
367  string devicename = "CPU";
368  bool list = false;
369 
370  /* List devices for which support is compiled in. */
371  vector<DeviceType> types = Device::available_types();
372  foreach (DeviceType type, types) {
373  if (device_names != "")
374  device_names += ", ";
375 
376  device_names += Device::string_from_type(type);
377  }
378 
379  /* shading system */
380  string ssname = "svm";
381 
382  /* parse options */
383  ArgParse ap;
384  bool help = false, profile = false, debug = false, version = false;
385  int verbosity = 1;
386 
387  ap.options("Usage: cycles [options] file.xml",
388  "%*",
389  files_parse,
390  "",
391  "--device %s",
392  &devicename,
393  ("Devices to use: " + device_names).c_str(),
394 #ifdef WITH_OSL
395  "--shadingsys %s",
396  &ssname,
397  "Shading system to use: svm, osl",
398 #endif
399  "--background",
401  "Render in background, without user interface",
402  "--quiet",
403  &options.quiet,
404  "In background mode, don't print progress messages",
405  "--samples %d",
407  "Number of samples to render",
408  "--output %s",
410  "File path to write output image",
411  "--threads %d",
413  "CPU Rendering Threads",
414  "--width %d",
415  &options.width,
416  "Window width in pixel",
417  "--height %d",
418  &options.height,
419  "Window height in pixel",
420  "--tile-size %d",
422  "Tile size in pixels",
423  "--list-devices",
424  &list,
425  "List information about all available devices",
426  "--profile",
427  &profile,
428  "Enable profile logging",
429 #ifdef WITH_CYCLES_LOGGING
430  "--debug",
431  &debug,
432  "Enable debug logging",
433  "--verbose %d",
434  &verbosity,
435  "Set verbosity of the logger",
436 #endif
437  "--help",
438  &help,
439  "Print help message",
440  "--version",
441  &version,
442  "Print version number",
443  NULL);
444 
445  if (ap.parse(argc, argv) < 0) {
446  fprintf(stderr, "%s\n", ap.geterror().c_str());
447  ap.usage();
448  exit(EXIT_FAILURE);
449  }
450 
451  if (debug) {
453  util_logging_verbosity_set(verbosity);
454  }
455 
456  if (list) {
458  printf("Devices:\n");
459 
460  foreach (DeviceInfo &info, devices) {
461  printf(" %-10s%s%s\n",
462  Device::string_from_type(info.type).c_str(),
463  info.description.c_str(),
464  (info.display_device) ? " (display)" : "");
465  }
466 
467  exit(EXIT_SUCCESS);
468  }
469  else if (version) {
470  printf("%s\n", CYCLES_VERSION_STRING);
471  exit(EXIT_SUCCESS);
472  }
473  else if (help || options.filepath == "") {
474  ap.usage();
475  exit(EXIT_SUCCESS);
476  }
477 
479 
480  if (ssname == "osl")
482  else if (ssname == "svm")
484 
485 #ifndef WITH_CYCLES_STANDALONE_GUI
487 #endif
488 
489  if (options.session_params.tile_size > 0) {
491  }
492 
493  /* find matching device */
494  DeviceType device_type = Device::type_from_string(devicename.c_str());
496 
497  bool device_available = false;
498  if (!devices.empty()) {
500  device_available = true;
501  }
502 
503  /* handle invalid configurations */
504  if (options.session_params.device.type == DEVICE_NONE || !device_available) {
505  fprintf(stderr, "Unknown device: %s\n", devicename.c_str());
506  exit(EXIT_FAILURE);
507  }
508 #ifdef WITH_OSL
509  else if (!(ssname == "osl" || ssname == "svm")) {
510  fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str());
511  exit(EXIT_FAILURE);
512  }
515  fprintf(stderr, "OSL shading system only works with CPU device\n");
516  exit(EXIT_FAILURE);
517  }
518 #endif
519  else if (options.session_params.samples < 0) {
520  fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples);
521  exit(EXIT_FAILURE);
522  }
523  else if (options.filepath == "") {
524  fprintf(stderr, "No file path specified\n");
525  exit(EXIT_FAILURE);
526  }
527 }
528 
530 
531 using namespace ccl;
532 
533 int main(int argc, const char **argv)
534 {
535  util_logging_init(argv[0]);
536  path_init();
537  options_parse(argc, argv);
538 
539 #ifdef WITH_CYCLES_STANDALONE_GUI
541 #endif
542  session_init();
543  options.session->wait();
544  session_exit();
545 #ifdef WITH_CYCLES_STANDALONE_GUI
546  }
547  else {
548  string title = "Cycles: " + path_filename(options.filepath);
549 
550  /* init/exit are callback so they run while GL is initialized */
551  window_main_loop(title.c_str(),
552  options.width,
553  options.height,
554  session_init,
555  session_exit,
556  resize,
557  display,
558  keyboard,
559  motion);
560  }
561 #endif
562 
563  return 0;
564 }
#define DEG2RADF(_deg)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
float float4[4]
int full_width
Definition: buffers.h:86
int height
Definition: buffers.h:72
int full_height
Definition: buffers.h:87
NODE_DECLARE int width
Definition: buffers.h:71
bool display_device
Definition: device/device.h:66
DeviceType type
Definition: device/device.h:62
string description
Definition: device/device.h:63
static vector< DeviceInfo > available_devices(uint device_type_mask=DEVICE_MASK_ALL)
static DeviceType type_from_string(const char *name)
static vector< DeviceType > available_types()
static string string_from_type(DeviceType type)
Definition: pass.h:48
void get_status(string &status_, string &substatus_) const
Definition: progress.h:290
void set_cancel(const string &cancel_message_)
Definition: progress.h:83
void get_time(double &total_time_, double &render_time_) const
Definition: progress.h:158
double get_progress() const
Definition: progress.h:190
void set_update_callback(function< void()> function)
Definition: progress.h:314
ShadingSystem shadingsystem
Definition: scene.h:139
DeviceInfo device
void set_pause(bool pause)
void set_display_driver(unique_ptr< DisplayDriver > driver)
void start()
Progress progress
void reset(const SessionParams &session_params, const BufferParams &buffer_params)
Scene * scene
void set_output_driver(unique_ptr< OutputDriver > driver)
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
static void session_init()
int main(int argc, const char **argv)
static void scene_init()
static void session_print_status()
static void session_exit()
static void options_parse(int argc, const char **argv)
static BufferParams & session_buffer_params()
CCL_NAMESPACE_BEGIN struct Options options
static void session_print(const string &str)
static int files_parse(int argc, const char *argv[])
void xml_read_file(Scene *scene, const char *filepath)
Definition: cycles_xml.cpp:712
#define function_bind
#define DEVICE_MASK(type)
Definition: device/device.h:58
DeviceType
Definition: device/device.h:36
@ DEVICE_NONE
Definition: device/device.h:37
@ DEVICE_CPU
Definition: device/device.h:38
int len
Definition: draw_manager.c:108
#define str(s)
ccl_device_inline Transform transform_rotate(float angle, float3 axis)
ccl_device_inline Transform transform_translate(float3 t)
@ PASS_COMBINED
Definition: kernel/types.h:338
CCL_NAMESPACE_BEGIN void util_logging_init(const char *argv0)
Definition: log.cpp:29
void util_logging_verbosity_set(int verbosity)
Definition: log.cpp:59
void util_logging_start()
Definition: log.cpp:46
static char ** types
Definition: makesdna.c:67
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define make_float3(x, y, z)
Definition: metal/compat.h:204
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
string path_filename(const string &path)
Definition: path.cpp:376
void path_init(const string &path, const string &user_path)
Definition: path.cpp:325
@ SHADINGSYSTEM_OSL
Definition: scene/shader.h:34
@ SHADINGSYSTEM_SVM
Definition: scene/shader.h:34
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22
bool string_endswith(const string_view s, const string_view end)
Definition: string.cpp:111
string string_to_lower(const string &s)
Definition: string.cpp:185
SceneParams scene_params
SessionParams session_params
Session * session
string output_pass
string output_filepath
T * create_node(Args &&...args)
Definition: scene.h:284
Integrator * integrator
Definition: scene.h:210
struct Object * camera
CCL_NAMESPACE_BEGIN double time_dt()
Definition: time.cpp:35
float max
#define CYCLES_VERSION_STRING
Definition: version.h:17
void window_main_loop(const char *title, int width, int height, WindowInitFunc initf, WindowExitFunc exitf, WindowResizeFunc resize, WindowDisplayFunc display, WindowKeyboardFunc keyboard, WindowMotionFunc motion)
Definition: window.cpp:259
void window_opengl_context_disable()
Definition: window.cpp:253
bool window_opengl_context_enable()
Definition: window.cpp:246
void window_display_info(const char *info)
Definition: window.cpp:75
void window_redraw()
Definition: window.cpp:347
void window_display_help()
Definition: window.cpp:96