Blender  V2.93
device_network.cpp
Go to the documentation of this file.
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 "device/device_network.h"
18 #include "device/device.h"
19 #include "device/device_intern.h"
20 
21 #include "util/util_foreach.h"
22 #include "util/util_logging.h"
23 
24 #if defined(WITH_NETWORK)
25 
27 
28 typedef map<device_ptr, device_ptr> PtrMap;
29 typedef vector<uint8_t> DataVector;
30 typedef map<device_ptr, DataVector> DataMap;
31 
32 /* tile list */
33 typedef vector<RenderTile> TileList;
34 
35 /* search a list of tiles and find the one that matches the passed render tile */
36 static TileList::iterator tile_list_find(TileList &tile_list, RenderTile &tile)
37 {
38  for (TileList::iterator it = tile_list.begin(); it != tile_list.end(); ++it)
39  if (tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample)
40  return it;
41  return tile_list.end();
42 }
43 
44 class NetworkDevice : public Device {
45  public:
46  boost::asio::io_service io_service;
47  tcp::socket socket;
48  device_ptr mem_counter;
49  DeviceTask the_task; /* todo: handle multiple tasks */
50 
51  thread_mutex rpc_lock;
52 
53  virtual bool show_samples() const
54  {
55  return false;
56  }
57 
58  NetworkDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, const char *address)
59  : Device(info, stats, profiler, true), socket(io_service)
60  {
61  error_func = NetworkError();
62  stringstream portstr;
63  portstr << SERVER_PORT;
64 
65  tcp::resolver resolver(io_service);
66  tcp::resolver::query query(address, portstr.str());
67  tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
68  tcp::resolver::iterator end;
69 
70  boost::system::error_code error = boost::asio::error::host_not_found;
71  while (error && endpoint_iterator != end) {
72  socket.close();
73  socket.connect(*endpoint_iterator++, error);
74  }
75 
76  if (error)
77  error_func.network_error(error.message());
78 
79  mem_counter = 0;
80  }
81 
82  ~NetworkDevice()
83  {
84  RPCSend snd(socket, &error_func, "stop");
85  snd.write();
86  }
87 
88  virtual BVHLayoutMask get_bvh_layout_mask() const
89  {
90  return BVH_LAYOUT_BVH2;
91  }
92 
93  void mem_alloc(device_memory &mem)
94  {
95  if (mem.name) {
96  VLOG(1) << "Buffer allocate: " << mem.name << ", "
97  << string_human_readable_number(mem.memory_size()) << " bytes. ("
98  << string_human_readable_size(mem.memory_size()) << ")";
99  }
100 
101  thread_scoped_lock lock(rpc_lock);
102 
103  mem.device_pointer = ++mem_counter;
104 
105  RPCSend snd(socket, &error_func, "mem_alloc");
106  snd.add(mem);
107  snd.write();
108  }
109 
110  void mem_copy_to(device_memory &mem)
111  {
112  thread_scoped_lock lock(rpc_lock);
113 
114  RPCSend snd(socket, &error_func, "mem_copy_to");
115 
116  snd.add(mem);
117  snd.write();
118  snd.write_buffer(mem.host_pointer, mem.memory_size());
119  }
120 
121  void mem_copy_from(device_memory &mem, int y, int w, int h, int elem)
122  {
123  thread_scoped_lock lock(rpc_lock);
124 
125  size_t data_size = mem.memory_size();
126 
127  RPCSend snd(socket, &error_func, "mem_copy_from");
128 
129  snd.add(mem);
130  snd.add(y);
131  snd.add(w);
132  snd.add(h);
133  snd.add(elem);
134  snd.write();
135 
136  RPCReceive rcv(socket, &error_func);
137  rcv.read_buffer(mem.host_pointer, data_size);
138  }
139 
140  void mem_zero(device_memory &mem)
141  {
142  thread_scoped_lock lock(rpc_lock);
143 
144  RPCSend snd(socket, &error_func, "mem_zero");
145 
146  snd.add(mem);
147  snd.write();
148  }
149 
150  void mem_free(device_memory &mem)
151  {
152  if (mem.device_pointer) {
153  thread_scoped_lock lock(rpc_lock);
154 
155  RPCSend snd(socket, &error_func, "mem_free");
156 
157  snd.add(mem);
158  snd.write();
159 
160  mem.device_pointer = 0;
161  }
162  }
163 
164  void const_copy_to(const char *name, void *host, size_t size)
165  {
166  thread_scoped_lock lock(rpc_lock);
167 
168  RPCSend snd(socket, &error_func, "const_copy_to");
169 
170  string name_string(name);
171 
172  snd.add(name_string);
173  snd.add(size);
174  snd.write();
175  snd.write_buffer(host, size);
176  }
177 
178  bool load_kernels(const DeviceRequestedFeatures &requested_features)
179  {
180  if (error_func.have_error())
181  return false;
182 
183  thread_scoped_lock lock(rpc_lock);
184 
185  RPCSend snd(socket, &error_func, "load_kernels");
186  snd.add(requested_features.experimental);
187  snd.add(requested_features.max_closure);
188  snd.add(requested_features.max_nodes_group);
189  snd.add(requested_features.nodes_features);
190  snd.write();
191 
192  bool result;
193  RPCReceive rcv(socket, &error_func);
194  rcv.read(result);
195 
196  return result;
197  }
198 
199  void task_add(DeviceTask &task)
200  {
201  thread_scoped_lock lock(rpc_lock);
202 
203  the_task = task;
204 
205  RPCSend snd(socket, &error_func, "task_add");
206  snd.add(task);
207  snd.write();
208  }
209 
210  void task_wait()
211  {
212  thread_scoped_lock lock(rpc_lock);
213 
214  RPCSend snd(socket, &error_func, "task_wait");
215  snd.write();
216 
217  lock.unlock();
218 
219  TileList the_tiles;
220 
221  /* todo: run this threaded for connecting to multiple clients */
222  for (;;) {
223  if (error_func.have_error())
224  break;
225 
226  RenderTile tile;
227 
228  lock.lock();
229  RPCReceive rcv(socket, &error_func);
230 
231  if (rcv.name == "acquire_tile") {
232  lock.unlock();
233 
234  /* todo: watch out for recursive calls! */
235  if (the_task.acquire_tile(this, tile)) { /* write return as bool */
236  the_tiles.push_back(tile);
237 
238  lock.lock();
239  RPCSend snd(socket, &error_func, "acquire_tile");
240  snd.add(tile);
241  snd.write();
242  lock.unlock();
243  }
244  else {
245  lock.lock();
246  RPCSend snd(socket, &error_func, "acquire_tile_none");
247  snd.write();
248  lock.unlock();
249  }
250  }
251  else if (rcv.name == "release_tile") {
252  rcv.read(tile);
253  lock.unlock();
254 
255  TileList::iterator it = tile_list_find(the_tiles, tile);
256  if (it != the_tiles.end()) {
257  tile.buffers = it->buffers;
258  the_tiles.erase(it);
259  }
260 
261  assert(tile.buffers != NULL);
262 
263  the_task.release_tile(tile);
264 
265  lock.lock();
266  RPCSend snd(socket, &error_func, "release_tile");
267  snd.write();
268  lock.unlock();
269  }
270  else if (rcv.name == "task_wait_done") {
271  lock.unlock();
272  break;
273  }
274  else
275  lock.unlock();
276  }
277  }
278 
279  void task_cancel()
280  {
281  thread_scoped_lock lock(rpc_lock);
282  RPCSend snd(socket, &error_func, "task_cancel");
283  snd.write();
284  }
285 
287  {
288  return 1;
289  }
290 
291  private:
292  NetworkError error_func;
293 };
294 
296  Stats &stats,
297  Profiler &profiler,
298  const char *address)
299 {
300  return new NetworkDevice(info, stats, profiler, address);
301 }
302 
304 {
305  DeviceInfo info;
306 
307  info.type = DEVICE_NETWORK;
308  info.description = "Network Device";
309  info.id = "NETWORK";
310  info.num = 0;
311 
312  /* todo: get this info from device */
313  info.has_volume_decoupled = false;
314  info.has_adaptive_stop_per_sample = false;
315  info.has_osl = false;
316  info.denoisers = DENOISER_NONE;
317 
318  devices.push_back(info);
319 }
320 
321 class DeviceServer {
322  public:
323  thread_mutex rpc_lock;
324 
325  void network_error(const string &message)
326  {
327  error_func.network_error(message);
328  }
329 
330  bool have_error()
331  {
332  return error_func.have_error();
333  }
334 
335  DeviceServer(Device *device_, tcp::socket &socket_)
336  : device(device_), socket(socket_), stop(false), blocked_waiting(false)
337  {
338  error_func = NetworkError();
339  }
340 
341  void listen()
342  {
343  /* receive remote function calls */
344  for (;;) {
345  listen_step();
346 
347  if (stop)
348  break;
349  }
350  }
351 
352  protected:
353  void listen_step()
354  {
355  thread_scoped_lock lock(rpc_lock);
356  RPCReceive rcv(socket, &error_func);
357 
358  if (rcv.name == "stop")
359  stop = true;
360  else
361  process(rcv, lock);
362  }
363 
364  /* create a memory buffer for a device buffer and insert it into mem_data */
365  DataVector &data_vector_insert(device_ptr client_pointer, size_t data_size)
366  {
367  /* create a new DataVector and insert it into mem_data */
368  pair<DataMap::iterator, bool> data_ins = mem_data.insert(
369  DataMap::value_type(client_pointer, DataVector()));
370 
371  /* make sure it was a unique insertion */
372  assert(data_ins.second);
373 
374  /* get a reference to the inserted vector */
375  DataVector &data_v = data_ins.first->second;
376 
377  /* size the vector */
378  data_v.resize(data_size);
379 
380  return data_v;
381  }
382 
383  DataVector &data_vector_find(device_ptr client_pointer)
384  {
385  DataMap::iterator i = mem_data.find(client_pointer);
386  assert(i != mem_data.end());
387  return i->second;
388  }
389 
390  /* setup mapping and reverse mapping of client_pointer<->real_pointer */
391  void pointer_mapping_insert(device_ptr client_pointer, device_ptr real_pointer)
392  {
393  pair<PtrMap::iterator, bool> mapins;
394 
395  /* insert mapping from client pointer to our real device pointer */
396  mapins = ptr_map.insert(PtrMap::value_type(client_pointer, real_pointer));
397  assert(mapins.second);
398 
399  /* insert reverse mapping from real our device pointer to client pointer */
400  mapins = ptr_imap.insert(PtrMap::value_type(real_pointer, client_pointer));
401  assert(mapins.second);
402  }
403 
404  device_ptr device_ptr_from_client_pointer(device_ptr client_pointer)
405  {
406  PtrMap::iterator i = ptr_map.find(client_pointer);
407  assert(i != ptr_map.end());
408  return i->second;
409  }
410 
411  device_ptr device_ptr_from_client_pointer_erase(device_ptr client_pointer)
412  {
413  PtrMap::iterator i = ptr_map.find(client_pointer);
414  assert(i != ptr_map.end());
415 
416  device_ptr result = i->second;
417 
418  /* erase the mapping */
419  ptr_map.erase(i);
420 
421  /* erase the reverse mapping */
422  PtrMap::iterator irev = ptr_imap.find(result);
423  assert(irev != ptr_imap.end());
424  ptr_imap.erase(irev);
425 
426  /* erase the data vector */
427  DataMap::iterator idata = mem_data.find(client_pointer);
428  assert(idata != mem_data.end());
429  mem_data.erase(idata);
430 
431  return result;
432  }
433 
434  /* note that the lock must be already acquired upon entry.
435  * This is necessary because the caller often peeks at
436  * the header and delegates control to here when it doesn't
437  * specifically handle the current RPC.
438  * The lock must be unlocked before returning */
439  void process(RPCReceive &rcv, thread_scoped_lock &lock)
440  {
441  if (rcv.name == "mem_alloc") {
442  string name;
443  network_device_memory mem(device);
444  rcv.read(mem, name);
445  lock.unlock();
446 
447  /* Allocate host side data buffer. */
448  size_t data_size = mem.memory_size();
449  device_ptr client_pointer = mem.device_pointer;
450 
451  DataVector &data_v = data_vector_insert(client_pointer, data_size);
452  mem.host_pointer = (data_size) ? (void *)&(data_v[0]) : 0;
453 
454  /* Perform the allocation on the actual device. */
455  device->mem_alloc(mem);
456 
457  /* Store a mapping to/from client_pointer and real device pointer. */
458  pointer_mapping_insert(client_pointer, mem.device_pointer);
459  }
460  else if (rcv.name == "mem_copy_to") {
461  string name;
462  network_device_memory mem(device);
463  rcv.read(mem, name);
464  lock.unlock();
465 
466  size_t data_size = mem.memory_size();
467  device_ptr client_pointer = mem.device_pointer;
468 
469  if (client_pointer) {
470  /* Lookup existing host side data buffer. */
471  DataVector &data_v = data_vector_find(client_pointer);
472  mem.host_pointer = (void *)&data_v[0];
473 
474  /* Translate the client pointer to a real device pointer. */
475  mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
476  }
477  else {
478  /* Allocate host side data buffer. */
479  DataVector &data_v = data_vector_insert(client_pointer, data_size);
480  mem.host_pointer = (data_size) ? (void *)&(data_v[0]) : 0;
481  }
482 
483  /* Copy data from network into memory buffer. */
484  rcv.read_buffer((uint8_t *)mem.host_pointer, data_size);
485 
486  /* Copy the data from the memory buffer to the device buffer. */
487  device->mem_copy_to(mem);
488 
489  if (!client_pointer) {
490  /* Store a mapping to/from client_pointer and real device pointer. */
491  pointer_mapping_insert(client_pointer, mem.device_pointer);
492  }
493  }
494  else if (rcv.name == "mem_copy_from") {
495  string name;
496  network_device_memory mem(device);
497  int y, w, h, elem;
498 
499  rcv.read(mem, name);
500  rcv.read(y);
501  rcv.read(w);
502  rcv.read(h);
503  rcv.read(elem);
504 
505  device_ptr client_pointer = mem.device_pointer;
506  mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
507 
508  DataVector &data_v = data_vector_find(client_pointer);
509 
510  mem.host_pointer = (device_ptr) & (data_v[0]);
511 
512  device->mem_copy_from(mem, y, w, h, elem);
513 
514  size_t data_size = mem.memory_size();
515 
516  RPCSend snd(socket, &error_func, "mem_copy_from");
517  snd.write();
518  snd.write_buffer((uint8_t *)mem.host_pointer, data_size);
519  lock.unlock();
520  }
521  else if (rcv.name == "mem_zero") {
522  string name;
523  network_device_memory mem(device);
524  rcv.read(mem, name);
525  lock.unlock();
526 
527  size_t data_size = mem.memory_size();
528  device_ptr client_pointer = mem.device_pointer;
529 
530  if (client_pointer) {
531  /* Lookup existing host side data buffer. */
532  DataVector &data_v = data_vector_find(client_pointer);
533  mem.host_pointer = (void *)&data_v[0];
534 
535  /* Translate the client pointer to a real device pointer. */
536  mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
537  }
538  else {
539  /* Allocate host side data buffer. */
540  DataVector &data_v = data_vector_insert(client_pointer, data_size);
541  mem.host_pointer = (void *) ? (device_ptr) & (data_v[0]) : 0;
542  }
543 
544  /* Zero memory. */
545  device->mem_zero(mem);
546 
547  if (!client_pointer) {
548  /* Store a mapping to/from client_pointer and real device pointer. */
549  pointer_mapping_insert(client_pointer, mem.device_pointer);
550  }
551  }
552  else if (rcv.name == "mem_free") {
553  string name;
554  network_device_memory mem(device);
555 
556  rcv.read(mem, name);
557  lock.unlock();
558 
559  device_ptr client_pointer = mem.device_pointer;
560 
561  mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
562 
563  device->mem_free(mem);
564  }
565  else if (rcv.name == "const_copy_to") {
566  string name_string;
567  size_t size;
568 
569  rcv.read(name_string);
570  rcv.read(size);
571 
572  vector<char> host_vector(size);
573  rcv.read_buffer(&host_vector[0], size);
574  lock.unlock();
575 
576  device->const_copy_to(name_string.c_str(), &host_vector[0], size);
577  }
578  else if (rcv.name == "load_kernels") {
579  DeviceRequestedFeatures requested_features;
580  rcv.read(requested_features.experimental);
581  rcv.read(requested_features.max_closure);
582  rcv.read(requested_features.max_nodes_group);
583  rcv.read(requested_features.nodes_features);
584 
585  bool result;
586  result = device->load_kernels(requested_features);
587  RPCSend snd(socket, &error_func, "load_kernels");
588  snd.add(result);
589  snd.write();
590  lock.unlock();
591  }
592  else if (rcv.name == "task_add") {
594 
595  rcv.read(task);
596  lock.unlock();
597 
598  if (task.buffer)
599  task.buffer = device_ptr_from_client_pointer(task.buffer);
600 
601  if (task.rgba_half)
602  task.rgba_half = device_ptr_from_client_pointer(task.rgba_half);
603 
604  if (task.rgba_byte)
605  task.rgba_byte = device_ptr_from_client_pointer(task.rgba_byte);
606 
607  if (task.shader_input)
608  task.shader_input = device_ptr_from_client_pointer(task.shader_input);
609 
610  if (task.shader_output)
611  task.shader_output = device_ptr_from_client_pointer(task.shader_output);
612 
613  task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
614  task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
615  task.update_progress_sample = function_bind(&DeviceServer::task_update_progress_sample,
616  this);
617  task.update_tile_sample = function_bind(&DeviceServer::task_update_tile_sample, this, _1);
618  task.get_cancel = function_bind(&DeviceServer::task_get_cancel, this);
619 
620  device->task_add(task);
621  }
622  else if (rcv.name == "task_wait") {
623  lock.unlock();
624 
625  blocked_waiting = true;
626  device->task_wait();
627  blocked_waiting = false;
628 
629  lock.lock();
630  RPCSend snd(socket, &error_func, "task_wait_done");
631  snd.write();
632  lock.unlock();
633  }
634  else if (rcv.name == "task_cancel") {
635  lock.unlock();
636  device->task_cancel();
637  }
638  else if (rcv.name == "acquire_tile") {
639  AcquireEntry entry;
640  entry.name = rcv.name;
641  rcv.read(entry.tile);
642  acquire_queue.push_back(entry);
643  lock.unlock();
644  }
645  else if (rcv.name == "acquire_tile_none") {
646  AcquireEntry entry;
647  entry.name = rcv.name;
648  acquire_queue.push_back(entry);
649  lock.unlock();
650  }
651  else if (rcv.name == "release_tile") {
652  AcquireEntry entry;
653  entry.name = rcv.name;
654  acquire_queue.push_back(entry);
655  lock.unlock();
656  }
657  else {
658  cout << "Error: unexpected RPC receive call \"" + rcv.name + "\"\n";
659  lock.unlock();
660  }
661  }
662 
663  bool task_acquire_tile(Device *, RenderTile &tile)
664  {
665  thread_scoped_lock acquire_lock(acquire_mutex);
666 
667  bool result = false;
668 
669  RPCSend snd(socket, &error_func, "acquire_tile");
670  snd.write();
671 
672  do {
673  if (blocked_waiting)
674  listen_step();
675 
676  /* todo: avoid busy wait loop */
677  thread_scoped_lock lock(rpc_lock);
678 
679  if (!acquire_queue.empty()) {
680  AcquireEntry entry = acquire_queue.front();
681  acquire_queue.pop_front();
682 
683  if (entry.name == "acquire_tile") {
684  tile = entry.tile;
685 
686  if (tile.buffer)
687  tile.buffer = ptr_map[tile.buffer];
688 
689  result = true;
690  break;
691  }
692  else if (entry.name == "acquire_tile_none") {
693  break;
694  }
695  else {
696  cout << "Error: unexpected acquire RPC receive call \"" + entry.name + "\"\n";
697  }
698  }
699  } while (acquire_queue.empty() && !stop && !have_error());
700 
701  return result;
702  }
703 
704  void task_update_progress_sample()
705  {
706  ; /* skip */
707  }
708 
709  void task_update_tile_sample(RenderTile &)
710  {
711  ; /* skip */
712  }
713 
714  void task_release_tile(RenderTile &tile)
715  {
716  thread_scoped_lock acquire_lock(acquire_mutex);
717 
718  if (tile.buffer)
719  tile.buffer = ptr_imap[tile.buffer];
720 
721  {
722  thread_scoped_lock lock(rpc_lock);
723  RPCSend snd(socket, &error_func, "release_tile");
724  snd.add(tile);
725  snd.write();
726  lock.unlock();
727  }
728 
729  do {
730  if (blocked_waiting)
731  listen_step();
732 
733  /* todo: avoid busy wait loop */
734  thread_scoped_lock lock(rpc_lock);
735 
736  if (!acquire_queue.empty()) {
737  AcquireEntry entry = acquire_queue.front();
738  acquire_queue.pop_front();
739 
740  if (entry.name == "release_tile") {
741  lock.unlock();
742  break;
743  }
744  else {
745  cout << "Error: unexpected release RPC receive call \"" + entry.name + "\"\n";
746  }
747  }
748  } while (acquire_queue.empty() && !stop);
749  }
750 
751  bool task_get_cancel()
752  {
753  return false;
754  }
755 
756  /* properties */
757  Device *device;
758  tcp::socket &socket;
759 
760  /* mapping of remote to local pointer */
761  PtrMap ptr_map;
762  PtrMap ptr_imap;
763  DataMap mem_data;
764 
765  struct AcquireEntry {
766  string name;
767  RenderTile tile;
768  };
769 
770  thread_mutex acquire_mutex;
771  list<AcquireEntry> acquire_queue;
772 
773  bool stop;
774  bool blocked_waiting;
775 
776  private:
777  NetworkError error_func;
778 
779  /* todo: free memory and device (osl) on network error */
780 };
781 
782 void Device::server_run()
783 {
784  try {
785  /* starts thread that responds to discovery requests */
786  ServerDiscovery discovery;
787 
788  for (;;) {
789  /* accept connection */
790  boost::asio::io_service io_service;
791  tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), SERVER_PORT));
792 
793  tcp::socket socket(io_service);
794  acceptor.accept(socket);
795 
796  string remote_address = socket.remote_endpoint().address().to_string();
797  printf("Connected to remote client at: %s\n", remote_address.c_str());
798 
799  DeviceServer server(this, socket);
800  server.listen();
801 
802  printf("Disconnected.\n");
803  }
804  }
805  catch (exception &e) {
806  fprintf(stderr, "Network server exception: %s\n", e.what());
807  }
808 }
809 
811 
812 #endif
_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 GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum query
_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
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void process(btMatrix3x3 &B, btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V)
Helper function of 3X3 SVD for processing 2X2 SVD.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
int BVHLayoutMask
Definition: bvh_params.h:39
int num
Definition: device.h:77
string id
Definition: device.h:76
bool has_osl
Definition: device.h:84
DenoiserTypeMask denoisers
Definition: device.h:88
bool has_adaptive_stop_per_sample
Definition: device.h:83
DeviceType type
Definition: device.h:74
string description
Definition: device.h:75
bool has_volume_decoupled
Definition: device.h:81
function< void(RenderTile &)> release_tile
Definition: device_task.h:161
function< bool(Device *device, RenderTile &, uint)> acquire_tile
Definition: device_task.h:158
Definition: device.h:293
virtual BVHLayoutMask get_bvh_layout_mask() const =0
virtual void const_copy_to(const char *name, void *host, size_t size)=0
virtual void mem_zero(device_memory &mem)=0
virtual void task_wait()=0
virtual void mem_copy_from(device_memory &mem, int y, int w, int h, int elem)=0
virtual void task_cancel()=0
virtual int get_split_task_count(DeviceTask &)
Definition: device.h:403
virtual void mem_free(device_memory &mem)=0
virtual void mem_copy_to(device_memory &mem)=0
friend class DeviceServer
Definition: device.h:487
virtual void task_add(DeviceTask &task)=0
virtual void mem_alloc(device_memory &mem)=0
virtual bool load_kernels(const DeviceRequestedFeatures &)
Definition: device.h:380
virtual bool show_samples() const
Definition: device.h:354
RenderBuffers * buffers
Definition: buffers.h:152
device_ptr buffer
Definition: buffers.h:146
int start_sample
Definition: buffers.h:138
const char * name
void * host_pointer
size_t memory_size()
device_ptr device_pointer
#define function_bind
@ DEVICE_NETWORK
Definition: device.h:48
void device_network_info(vector< DeviceInfo > &devices)
Device * device_network_create(DeviceInfo &info, Stats &stats, Profiler &profiler, const char *address)
@ DENOISER_NONE
Definition: device_task.h:41
#define CCL_NAMESPACE_END
@ BVH_LAYOUT_BVH2
static void error(const char *str)
Definition: meshlaplacian.c:65
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
struct blender::compositor::@172::@174 task
unsigned char uint8_t
Definition: stdint.h:81
#define VLOG(severity)
Definition: util_logging.h:50
string string_human_readable_size(size_t size)
string string_human_readable_number(size_t num)
std::unique_lock< std::mutex > thread_scoped_lock
Definition: util_thread.h:41
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex
Definition: util_thread.h:40
uint64_t device_ptr
Definition: util_types.h:62