1 // Copyright 2009-2021 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 
4 #include <vector>
5 
6 #include "../fb/DistributedFrameBuffer.h"
7 #include "MPICommon.h"
8 #include "OSPWork.h"
9 #include "common/Data.h"
10 #include "common/Library.h"
11 #include "common/ObjectHandle.h"
12 #include "common/World.h"
13 #include "geometry/GeometricModel.h"
14 #include "ospray/MPIDistributedDevice.h"
15 #include "render/RenderTask.h"
16 #include "rkcommon/array3D/for_each.h"
17 #include "rkcommon/utility/ArrayView.h"
18 #include "rkcommon/utility/OwnedArray.h"
19 #include "texture/Texture.h"
20 #include "volume/VolumetricModel.h"
21 
22 namespace ospray {
23 namespace mpi {
24 namespace work {
25 
FrameBufferInfo(const vec2i & size,OSPFrameBufferFormat format,uint32_t channels)26 FrameBufferInfo::FrameBufferInfo(
27     const vec2i &size, OSPFrameBufferFormat format, uint32_t channels)
28     : size(size), format(format), channels(channels)
29 {}
30 
pixelSize(uint32_t channel) const31 size_t FrameBufferInfo::pixelSize(uint32_t channel) const
32 {
33   switch (channel) {
34   case OSP_FB_COLOR:
35     switch (format) {
36     case OSP_FB_RGBA8:
37     case OSP_FB_SRGBA:
38       return sizeof(uint32_t);
39     case OSP_FB_RGBA32F:
40       return sizeof(vec4f);
41     default:
42       return 0;
43     }
44   case OSP_FB_DEPTH:
45     return channels & OSP_FB_DEPTH ? sizeof(float) : 0;
46   case OSP_FB_NORMAL:
47     return channels & OSP_FB_NORMAL ? sizeof(vec3f) : 0;
48   case OSP_FB_ALBEDO:
49     return channels & OSP_FB_ALBEDO ? sizeof(vec3f) : 0;
50   default:
51     return 0;
52   }
53 }
54 
getNumPixels() const55 size_t FrameBufferInfo::getNumPixels() const
56 {
57   return size.x * size.y;
58 }
59 
getSharedDataHandle(int64_t handle) const60 Data *OSPState::getSharedDataHandle(int64_t handle) const
61 {
62   auto fnd = appSharedData.find(handle);
63   if (fnd != appSharedData.end()) {
64     return fnd->second;
65   }
66   return nullptr;
67 }
68 
newRenderer(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)69 void newRenderer(
70     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
71 {
72   int64_t handle = 0;
73   std::string type;
74   cmdBuf >> handle >> type;
75   state.objects[handle] = ospNewRenderer(type.c_str());
76 }
77 
newWorld(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)78 void newWorld(
79     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
80 {
81   int64_t handle = 0;
82   cmdBuf >> handle;
83   state.objects[handle] = ospNewWorld();
84 }
85 
newGeometry(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)86 void newGeometry(
87     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
88 {
89   int64_t handle = 0;
90   std::string type;
91   cmdBuf >> handle >> type;
92   state.objects[handle] = ospNewGeometry(type.c_str());
93 }
94 
newGeometricModel(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)95 void newGeometricModel(
96     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
97 {
98   int64_t handle = 0;
99   int64_t geomHandle = 0;
100   cmdBuf >> handle >> geomHandle;
101   state.objects[handle] =
102       ospNewGeometricModel(state.getObject<OSPGeometry>(geomHandle));
103 }
104 
newVolume(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)105 void newVolume(
106     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
107 {
108   int64_t handle = 0;
109   std::string type;
110   cmdBuf >> handle >> type;
111   state.objects[handle] = ospNewVolume(type.c_str());
112 }
113 
newVolumetricModel(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)114 void newVolumetricModel(
115     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
116 {
117   int64_t handle = 0;
118   int64_t volHandle = 0;
119   cmdBuf >> handle >> volHandle;
120   state.objects[handle] =
121       ospNewVolumetricModel(state.getObject<OSPVolume>(volHandle));
122 }
123 
newCamera(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)124 void newCamera(
125     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
126 {
127   int64_t handle = 0;
128   std::string type;
129   cmdBuf >> handle >> type;
130   state.objects[handle] = ospNewCamera(type.c_str());
131 }
132 
newTransferFunction(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)133 void newTransferFunction(
134     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
135 {
136   int64_t handle = 0;
137   std::string type;
138   cmdBuf >> handle >> type;
139   state.objects[handle] = ospNewTransferFunction(type.c_str());
140 }
141 
newImageOperation(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)142 void newImageOperation(
143     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
144 {
145   int64_t handle = 0;
146   std::string type;
147   cmdBuf >> handle >> type;
148   state.objects[handle] = ospNewImageOperation(type.c_str());
149 }
150 
newMaterial(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)151 void newMaterial(
152     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
153 {
154   int64_t handle = 0;
155   std::string type;
156   cmdBuf >> handle >> type;
157   state.objects[handle] = ospNewMaterial(nullptr, type.c_str());
158 }
159 
newLight(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)160 void newLight(
161     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
162 {
163   int64_t handle = 0;
164   std::string type;
165   cmdBuf >> handle >> type;
166   state.objects[handle] = ospNewLight(type.c_str());
167 }
168 
dataTransfer(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)169 void dataTransfer(OSPState &state,
170     networking::BufferReader &cmdBuf,
171     networking::Fabric &fabric)
172 {
173   using namespace utility;
174 
175   OSPDataType type;
176   vec3ul numItems = 0;
177   cmdBuf >> type >> numItems;
178 
179   Data *data = new Data(type, numItems);
180 
181   const uint64_t nbytes = data->size() * sizeOf(type);
182   auto view = std::make_shared<ArrayView<uint8_t>>(
183       reinterpret_cast<uint8_t *>(data->data()), nbytes);
184   fabric.recvBcast(*view);
185 
186   state.dataTransfers.push(data);
187 }
188 
retrieveData(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &,const OSPDataType type,const vec3ul numItems,Data * outputData)189 Data *retrieveData(OSPState &state,
190     networking::BufferReader &cmdBuf,
191     networking::Fabric &,
192     const OSPDataType type,
193     const vec3ul numItems,
194     Data *outputData)
195 {
196   using namespace utility;
197   uint32_t dataInline = 0;
198   cmdBuf >> dataInline;
199   const uint64_t nbytes = numItems.x * numItems.y * numItems.z * sizeOf(type);
200   if (dataInline) {
201     // If the data is inline we copy it out of the command buffer into
202     // a fixed array, since the command buffer will be destroyed after
203     // processing it
204     if (!outputData) {
205       outputData = new Data(type, numItems);
206     }
207     cmdBuf.read(outputData->data(), nbytes);
208   } else {
209     // All large data is sent before the command buffer using it, and will be
210     // in the state's data transfers list in order by the command referencing it
211     auto data = state.dataTransfers.front();
212     state.dataTransfers.pop();
213 
214     if (outputData) {
215       // All data on the workers is compact, with the compaction done by the
216       // app rank before sending
217       std::memcpy(outputData->data(), data->data(), nbytes);
218     } else {
219       outputData = data;
220     }
221   }
222 
223   // If the data type is managed we need to convert the handles back into
224   // OSPObjects and increment the refcount because we're populating the data
225   // object manually
226   if (mpicommon::isManagedObject(type)) {
227     for (size_t i = 0; i < array3D::longProduct(numItems); ++i) {
228       char *addr = outputData->data() + i * sizeOf(type);
229       int64_t *h = reinterpret_cast<int64_t *>(addr);
230       OSPObject *obj = reinterpret_cast<OSPObject *>(addr);
231       *obj = state.objects[*h];
232 
233       ManagedObject *m = lookupObject<ManagedObject>(*obj);
234       m->refInc();
235     }
236   }
237 
238   return outputData;
239 }
240 
newSharedData(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)241 void newSharedData(OSPState &state,
242     networking::BufferReader &cmdBuf,
243     networking::Fabric &fabric)
244 {
245   using namespace utility;
246 
247   int64_t handle = 0;
248   OSPDataType format;
249   vec3ul numItems = 0;
250   cmdBuf >> handle >> format >> numItems;
251 
252   auto data = retrieveData(state, cmdBuf, fabric, format, numItems, nullptr);
253 
254   state.objects[handle] = (OSPData)data;
255   state.appSharedData[handle] = data;
256 }
257 
newData(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)258 void newData(
259     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
260 {
261   int64_t handle = 0;
262   OSPDataType format;
263   vec3ul numItems = 0;
264   cmdBuf >> handle >> format >> numItems;
265 
266   state.objects[handle] =
267       ospNewData(format, numItems.x, numItems.y, numItems.z);
268 }
269 
copyData(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)270 void copyData(
271     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
272 {
273   int64_t sourceHandle = 0;
274   int64_t destinationHandle = 0;
275   vec3ul destinationIndex = 0;
276   cmdBuf >> sourceHandle >> destinationHandle >> destinationIndex;
277 
278   ospCopyData(state.getObject<OSPData>(sourceHandle),
279       state.getObject<OSPData>(destinationHandle),
280       destinationIndex.x,
281       destinationIndex.y,
282       destinationIndex.z);
283 }
284 
newTexture(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)285 void newTexture(
286     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
287 {
288   int64_t handle = 0;
289   std::string type;
290   cmdBuf >> handle >> type;
291   state.objects[handle] = ospNewTexture(type.c_str());
292 }
293 
newGroup(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)294 void newGroup(
295     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
296 {
297   int64_t handle = 0;
298   cmdBuf >> handle;
299   state.objects[handle] = ospNewGroup();
300 }
301 
newInstance(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)302 void newInstance(
303     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
304 {
305   int64_t handle = 0;
306   int64_t groupHandle = 0;
307   cmdBuf >> handle >> groupHandle;
308   state.objects[handle] =
309       ospNewInstance(state.getObject<OSPGroup>(groupHandle));
310 }
311 
commit(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)312 void commit(OSPState &state,
313     networking::BufferReader &cmdBuf,
314     networking::Fabric &fabric)
315 {
316   int64_t handle = 0;
317   cmdBuf >> handle;
318 
319   // If it's a data being committed, we need to retrieve the updated data
320   Data *d = state.getSharedDataHandle(handle);
321   if (d) {
322     retrieveData(state, cmdBuf, fabric, d->type, d->numItems, d);
323   }
324 
325   ospCommit(state.objects[handle]);
326 }
327 
release(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)328 void release(
329     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
330 {
331   int64_t handle = 0;
332   cmdBuf >> handle;
333   ospRelease(state.objects[handle]);
334   // Note: we keep the handle in the state.objects list as it may be referenced
335   // by other objects in the scene as a parameter or data.
336 
337   // Check if we can release a referenced framebuffer info
338   {
339     auto fnd = state.framebuffers.find(handle);
340     if (fnd != state.framebuffers.end()) {
341       OSPObject obj = state.objects[handle];
342       ManagedObject *m = lookupDistributedObject<ManagedObject>(obj);
343       // Framebuffers are given an extra ref count by the worker so that
344       // we can track the lifetime of their framebuffer info. Use count == 1
345       // means only the worker rank has a reference to the object
346       if (m->useCount() == 1) {
347         ospRelease(state.objects[handle]);
348         state.framebuffers.erase(fnd);
349       }
350     }
351   }
352 
353   if (state.getSharedDataHandle(handle)) {
354     state.appSharedData.erase(handle);
355   }
356 }
357 
retain(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)358 void retain(
359     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
360 {
361   int64_t handle = 0;
362   cmdBuf >> handle;
363   ospRetain(state.objects[handle]);
364 }
365 
loadModule(OSPState &,networking::BufferReader & cmdBuf,networking::Fabric &)366 void loadModule(
367     OSPState &, networking::BufferReader &cmdBuf, networking::Fabric &)
368 {
369   std::string module;
370   cmdBuf >> module;
371   ospLoadModule(module.c_str());
372 }
373 
createFramebuffer(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)374 void createFramebuffer(
375     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
376 {
377   int64_t handle = 0;
378   vec2i size(0, 0);
379   uint32_t format;
380   uint32_t channels = 0;
381   cmdBuf >> handle >> size >> format >> channels;
382   state.objects[handle] =
383       ospNewFrameBuffer(size.x, size.y, (OSPFrameBufferFormat)format, channels);
384   state.framebuffers[handle] =
385       FrameBufferInfo(size, (OSPFrameBufferFormat)format, channels);
386 
387   // Offload device keeps +1 ref for tracking the lifetime of the framebuffer
388   ospRetain(state.objects[handle]);
389 }
390 
mapFramebuffer(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)391 void mapFramebuffer(OSPState &state,
392     networking::BufferReader &cmdBuf,
393     networking::Fabric &fabric)
394 {
395   // Map the channel and send the image back over the fabric
396   int64_t handle = 0;
397   uint32_t channel = 0;
398   cmdBuf >> handle >> channel;
399 
400   if (mpicommon::worker.rank == 0) {
401     using namespace utility;
402 
403     const FrameBufferInfo &fbInfo = state.framebuffers[handle];
404     uint64_t nbytes = fbInfo.pixelSize(channel) * fbInfo.getNumPixels();
405 
406     auto bytesView = std::make_shared<OwnedArray<uint8_t>>(
407         reinterpret_cast<uint8_t *>(&nbytes), sizeof(nbytes));
408     fabric.send(bytesView, 0);
409 
410     if (nbytes != 0) {
411       OSPFrameBuffer fb = state.getObject<OSPFrameBuffer>(handle);
412       void *map = const_cast<void *>(
413           ospMapFrameBuffer(fb, (OSPFrameBufferChannel)channel));
414 
415       auto fbView = std::make_shared<OwnedArray<uint8_t>>(
416           reinterpret_cast<uint8_t *>(map), nbytes);
417 
418       fabric.send(fbView, 0);
419       ospUnmapFrameBuffer(map, fb);
420     }
421   }
422 }
423 
getVariance(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)424 void getVariance(OSPState &state,
425     networking::BufferReader &cmdBuf,
426     networking::Fabric &fabric)
427 {
428   // Map the channel and send the image back over the fabric
429   int64_t handle = 0;
430   cmdBuf >> handle;
431 
432   if (mpicommon::worker.rank == 0) {
433     using namespace utility;
434 
435     float variance = ospGetVariance(state.getObject<OSPFrameBuffer>(handle));
436 
437     auto bytesView = std::make_shared<OwnedArray<uint8_t>>(
438         reinterpret_cast<uint8_t *>(&variance), sizeof(variance));
439     fabric.send(bytesView, 0);
440   }
441 }
442 
resetAccumulation(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)443 void resetAccumulation(
444     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
445 {
446   int64_t handle = 0;
447   cmdBuf >> handle;
448   ospResetAccumulation(state.getObject<OSPFrameBuffer>(handle));
449 }
450 
renderFrame(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)451 void renderFrame(
452     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
453 {
454   int64_t futureHandle = 0;
455   int64_t fbHandle = 0;
456   int64_t rendererHandle = 0;
457   int64_t cameraHandle = 0;
458   int64_t worldHandle = 0;
459   cmdBuf >> fbHandle >> rendererHandle >> cameraHandle >> worldHandle
460       >> futureHandle;
461   state.objects[futureHandle] =
462       ospRenderFrame(state.getObject<OSPFrameBuffer>(fbHandle),
463           state.getObject<OSPRenderer>(rendererHandle),
464           state.getObject<OSPCamera>(cameraHandle),
465           state.getObject<OSPWorld>(worldHandle));
466 }
467 
468 template <typename T>
setParam(networking::BufferReader & cmdBuf,OSPObject obj,const std::string & param,OSPDataType type)469 void setParam(networking::BufferReader &cmdBuf,
470     OSPObject obj,
471     const std::string &param,
472     OSPDataType type)
473 {
474   T val;
475   cmdBuf >> val;
476   ospSetParam(obj, param.c_str(), type, &val);
477 }
478 
setParam(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)479 void setParam(
480     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
481 {
482   int64_t handle = 0;
483   std::string param;
484   OSPDataType type;
485   cmdBuf >> handle >> param >> type;
486 
487   // OSP_OBJECT use the same style of setting param since it's just a handle
488   if (mpicommon::isManagedObject(type)) {
489     int64_t val = 0;
490     cmdBuf >> val;
491     ospSetParam(
492         state.objects[handle], param.c_str(), type, &state.objects[val]);
493   } else {
494     switch (type) {
495     case OSP_STRING: {
496       std::string val;
497       cmdBuf >> val;
498       ospSetParam(state.objects[handle], param.c_str(), type, val.c_str());
499       break;
500     }
501     case OSP_BOOL:
502       setParam<bool>(cmdBuf, state.objects[handle], param, type);
503       break;
504     case OSP_CHAR:
505     case OSP_BYTE:
506       setParam<char>(cmdBuf, state.objects[handle], param, type);
507       break;
508     case OSP_VEC2UC:
509       setParam<vec2uc>(cmdBuf, state.objects[handle], param, type);
510       break;
511     case OSP_VEC3UC:
512       setParam<vec3uc>(cmdBuf, state.objects[handle], param, type);
513       break;
514     case OSP_VEC4UC:
515       setParam<vec4uc>(cmdBuf, state.objects[handle], param, type);
516       break;
517     case OSP_SHORT:
518       setParam<short>(cmdBuf, state.objects[handle], param, type);
519       break;
520     case OSP_USHORT:
521       setParam<unsigned short>(cmdBuf, state.objects[handle], param, type);
522       break;
523     case OSP_INT:
524       setParam<int>(cmdBuf, state.objects[handle], param, type);
525       break;
526     case OSP_VEC2I:
527       setParam<vec2i>(cmdBuf, state.objects[handle], param, type);
528       break;
529     case OSP_VEC3I:
530       setParam<vec3i>(cmdBuf, state.objects[handle], param, type);
531       break;
532     case OSP_VEC4I:
533       setParam<vec4i>(cmdBuf, state.objects[handle], param, type);
534       break;
535     case OSP_UINT:
536       setParam<unsigned int>(cmdBuf, state.objects[handle], param, type);
537       break;
538     case OSP_VEC2UI:
539       setParam<vec2ui>(cmdBuf, state.objects[handle], param, type);
540       break;
541     case OSP_VEC3UI:
542       setParam<vec3ui>(cmdBuf, state.objects[handle], param, type);
543       break;
544     case OSP_VEC4UI:
545       setParam<vec4ui>(cmdBuf, state.objects[handle], param, type);
546       break;
547     case OSP_LONG:
548       setParam<long>(cmdBuf, state.objects[handle], param, type);
549       break;
550     case OSP_VEC2L:
551       setParam<vec2l>(cmdBuf, state.objects[handle], param, type);
552       break;
553     case OSP_VEC3L:
554       setParam<vec3l>(cmdBuf, state.objects[handle], param, type);
555       break;
556     case OSP_VEC4L:
557       setParam<vec4l>(cmdBuf, state.objects[handle], param, type);
558       break;
559     case OSP_ULONG:
560       setParam<unsigned long>(cmdBuf, state.objects[handle], param, type);
561       break;
562     case OSP_VEC2UL:
563       setParam<vec2ul>(cmdBuf, state.objects[handle], param, type);
564       break;
565     case OSP_VEC3UL:
566       setParam<vec3ul>(cmdBuf, state.objects[handle], param, type);
567       break;
568     case OSP_VEC4UL:
569       setParam<vec4ul>(cmdBuf, state.objects[handle], param, type);
570       break;
571     case OSP_FLOAT:
572       setParam<float>(cmdBuf, state.objects[handle], param, type);
573       break;
574     case OSP_VEC2F:
575       setParam<vec2f>(cmdBuf, state.objects[handle], param, type);
576       break;
577     case OSP_VEC3F:
578       setParam<vec3f>(cmdBuf, state.objects[handle], param, type);
579       break;
580     case OSP_VEC4F:
581       setParam<vec4f>(cmdBuf, state.objects[handle], param, type);
582       break;
583     case OSP_DOUBLE:
584       setParam<double>(cmdBuf, state.objects[handle], param, type);
585       break;
586     case OSP_BOX1I:
587       setParam<box1i>(cmdBuf, state.objects[handle], param, type);
588       break;
589     case OSP_BOX2I:
590       setParam<box2i>(cmdBuf, state.objects[handle], param, type);
591       break;
592     case OSP_BOX3I:
593       setParam<box3i>(cmdBuf, state.objects[handle], param, type);
594       break;
595     case OSP_BOX4I:
596       setParam<box4i>(cmdBuf, state.objects[handle], param, type);
597       break;
598     case OSP_BOX1F:
599       setParam<box1f>(cmdBuf, state.objects[handle], param, type);
600       break;
601     case OSP_BOX2F:
602       setParam<box2f>(cmdBuf, state.objects[handle], param, type);
603       break;
604     case OSP_BOX3F:
605       setParam<box3f>(cmdBuf, state.objects[handle], param, type);
606       break;
607     case OSP_BOX4F:
608       setParam<box4f>(cmdBuf, state.objects[handle], param, type);
609       break;
610     case OSP_LINEAR2F:
611       setParam<linear2f>(cmdBuf, state.objects[handle], param, type);
612       break;
613     case OSP_LINEAR3F:
614       setParam<linear3f>(cmdBuf, state.objects[handle], param, type);
615       break;
616     case OSP_AFFINE2F:
617       setParam<affine2f>(cmdBuf, state.objects[handle], param, type);
618       break;
619     case OSP_AFFINE3F:
620       setParam<affine3f>(cmdBuf, state.objects[handle], param, type);
621       break;
622     default:
623       throw std::runtime_error("Unrecognized param type!");
624     }
625   }
626 }
627 
removeParam(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)628 void removeParam(
629     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
630 {
631   int64_t handle = 0;
632   std::string param;
633   cmdBuf >> handle >> param;
634   ospRemoveParam(state.objects[handle], param.c_str());
635 }
636 
pick(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)637 void pick(OSPState &state,
638     networking::BufferReader &cmdBuf,
639     networking::Fabric &fabric)
640 {
641   int64_t fbHandle = 0;
642   int64_t rendererHandle = 0;
643   int64_t cameraHandle = 0;
644   int64_t worldHandle = 0;
645   vec2f screenPos;
646   cmdBuf >> fbHandle >> rendererHandle >> cameraHandle >> worldHandle
647       >> screenPos;
648 
649   OSPPickResult res;
650   ospPick(&res,
651       state.getObject<OSPFrameBuffer>(fbHandle),
652       state.getObject<OSPRenderer>(rendererHandle),
653       state.getObject<OSPCamera>(cameraHandle),
654       state.getObject<OSPWorld>(worldHandle),
655       screenPos.x,
656       screenPos.y);
657 
658   if (mpicommon::worker.rank == 0) {
659     using namespace utility;
660     auto view = std::make_shared<OwnedArray<uint8_t>>(
661         reinterpret_cast<uint8_t *>(&res), sizeof(OSPPickResult));
662     fabric.send(view, 0);
663   }
664 }
665 
getBounds(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)666 void getBounds(OSPState &state,
667     networking::BufferReader &cmdBuf,
668     networking::Fabric &fabric)
669 {
670   int64_t handle = 0;
671   cmdBuf >> handle;
672 
673   OSPBounds res = ospGetBounds(state.objects[handle]);
674 
675   if (mpicommon::worker.rank == 0) {
676     using namespace utility;
677     auto view = std::make_shared<OwnedArray<uint8_t>>(
678         reinterpret_cast<uint8_t *>(&res), sizeof(OSPBounds));
679     fabric.send(view, 0);
680   }
681 }
682 
futureIsReady(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)683 void futureIsReady(OSPState &state,
684     networking::BufferReader &cmdBuf,
685     networking::Fabric &fabric)
686 {
687   int64_t handle = 0;
688   uint32_t event = 0;
689   cmdBuf >> handle >> event;
690   int ready =
691       ospIsReady(state.getObject<OSPFuture>(handle), (OSPSyncEvent)event);
692 
693   if (mpicommon::worker.rank == 0) {
694     using namespace utility;
695     auto view = std::make_shared<OwnedArray<uint8_t>>(
696         reinterpret_cast<uint8_t *>(&ready), sizeof(ready));
697     fabric.send(view, 0);
698   }
699 }
700 
futureWait(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)701 void futureWait(OSPState &state,
702     networking::BufferReader &cmdBuf,
703     networking::Fabric &fabric)
704 {
705   int64_t handle = 0;
706   uint32_t event = 0;
707   cmdBuf >> handle >> event;
708   ospWait(state.getObject<OSPFuture>(handle), (OSPSyncEvent)event);
709 
710   if (mpicommon::worker.rank == 0) {
711     using namespace utility;
712     auto view = std::make_shared<OwnedArray<uint8_t>>(
713         reinterpret_cast<uint8_t *>(&event), sizeof(event));
714     fabric.send(view, 0);
715   }
716 }
717 
futureCancel(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric &)718 void futureCancel(
719     OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &)
720 {
721   int64_t handle = 0;
722   cmdBuf >> handle;
723   ospCancel(state.getObject<OSPFuture>(handle));
724 }
725 
futureGetProgress(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)726 void futureGetProgress(OSPState &state,
727     networking::BufferReader &cmdBuf,
728     networking::Fabric &fabric)
729 {
730   int64_t handle = 0;
731   cmdBuf >> handle;
732   float progress = ospGetProgress(state.getObject<OSPFuture>(handle));
733 
734   if (mpicommon::worker.rank == 0) {
735     using namespace utility;
736     auto view = std::make_shared<OwnedArray<uint8_t>>(
737         reinterpret_cast<uint8_t *>(&progress), sizeof(progress));
738     fabric.send(view, 0);
739   }
740 }
741 
futureGetTaskDuration(OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)742 void futureGetTaskDuration(OSPState &state,
743     networking::BufferReader &cmdBuf,
744     networking::Fabric &fabric)
745 {
746   int64_t handle = 0;
747   cmdBuf >> handle;
748   float progress = ospGetTaskDuration(state.getObject<OSPFuture>(handle));
749 
750   if (mpicommon::worker.rank == 0) {
751     using namespace utility;
752     auto view = std::make_shared<OwnedArray<uint8_t>>(
753         reinterpret_cast<uint8_t *>(&progress), sizeof(progress));
754     fabric.send(view, 0);
755   }
756 }
757 
dispatchWork(TAG t,OSPState & state,networking::BufferReader & cmdBuf,networking::Fabric & fabric)758 void dispatchWork(TAG t,
759     OSPState &state,
760     networking::BufferReader &cmdBuf,
761     networking::Fabric &fabric)
762 {
763   switch (t) {
764   case NEW_RENDERER:
765     newRenderer(state, cmdBuf, fabric);
766     break;
767   case NEW_WORLD:
768     newWorld(state, cmdBuf, fabric);
769     break;
770   case NEW_GEOMETRY:
771     newGeometry(state, cmdBuf, fabric);
772     break;
773   case NEW_GEOMETRIC_MODEL:
774     newGeometricModel(state, cmdBuf, fabric);
775     break;
776   case NEW_VOLUME:
777     newVolume(state, cmdBuf, fabric);
778     break;
779   case NEW_VOLUMETRIC_MODEL:
780     newVolumetricModel(state, cmdBuf, fabric);
781     break;
782   case NEW_CAMERA:
783     newCamera(state, cmdBuf, fabric);
784     break;
785   case NEW_TRANSFER_FUNCTION:
786     newTransferFunction(state, cmdBuf, fabric);
787     break;
788   case NEW_IMAGE_OPERATION:
789     newImageOperation(state, cmdBuf, fabric);
790     break;
791   case NEW_MATERIAL:
792     newMaterial(state, cmdBuf, fabric);
793     break;
794   case NEW_LIGHT:
795     newLight(state, cmdBuf, fabric);
796     break;
797   case DATA_TRANSFER:
798     dataTransfer(state, cmdBuf, fabric);
799     break;
800   case NEW_SHARED_DATA:
801     newSharedData(state, cmdBuf, fabric);
802     break;
803   case NEW_DATA:
804     newData(state, cmdBuf, fabric);
805     break;
806   case COPY_DATA:
807     copyData(state, cmdBuf, fabric);
808     break;
809   case NEW_TEXTURE:
810     newTexture(state, cmdBuf, fabric);
811     break;
812   case NEW_GROUP:
813     newGroup(state, cmdBuf, fabric);
814     break;
815   case NEW_INSTANCE:
816     newInstance(state, cmdBuf, fabric);
817     break;
818   case COMMIT:
819     commit(state, cmdBuf, fabric);
820     break;
821   case RELEASE:
822     release(state, cmdBuf, fabric);
823     break;
824   case RETAIN:
825     retain(state, cmdBuf, fabric);
826     break;
827   case LOAD_MODULE:
828     loadModule(state, cmdBuf, fabric);
829     break;
830   case CREATE_FRAMEBUFFER:
831     createFramebuffer(state, cmdBuf, fabric);
832     break;
833   case MAP_FRAMEBUFFER:
834     mapFramebuffer(state, cmdBuf, fabric);
835     break;
836   case GET_VARIANCE:
837     getVariance(state, cmdBuf, fabric);
838     break;
839   case RESET_ACCUMULATION:
840     resetAccumulation(state, cmdBuf, fabric);
841     break;
842   case RENDER_FRAME:
843     renderFrame(state, cmdBuf, fabric);
844     break;
845   case SET_PARAM:
846     setParam(state, cmdBuf, fabric);
847     break;
848   case REMOVE_PARAM:
849     removeParam(state, cmdBuf, fabric);
850     break;
851   case PICK:
852     pick(state, cmdBuf, fabric);
853     break;
854   case GET_BOUNDS:
855     getBounds(state, cmdBuf, fabric);
856     break;
857   case FUTURE_IS_READY:
858     futureIsReady(state, cmdBuf, fabric);
859     break;
860   case FUTURE_WAIT:
861     futureWait(state, cmdBuf, fabric);
862     break;
863   case FUTURE_CANCEL:
864     futureCancel(state, cmdBuf, fabric);
865     break;
866   case FUTURE_GET_PROGRESS:
867     futureGetProgress(state, cmdBuf, fabric);
868     break;
869   case FUTURE_GET_TASK_DURATION:
870     futureGetTaskDuration(state, cmdBuf, fabric);
871     break;
872   case NONE:
873   default:
874     throw std::runtime_error("Invalid work tag!");
875   }
876 }
877 
tagName(work::TAG t)878 const char *tagName(work::TAG t)
879 {
880   switch (t) {
881   case NEW_RENDERER:
882     return "NEW_RENDERER";
883   case NEW_WORLD:
884     return "NEW_WORLD";
885   case NEW_GEOMETRY:
886     return "NEW_GEOMETRY";
887   case NEW_GEOMETRIC_MODEL:
888     return "NEW_GEOMETRIC_MODEL";
889   case NEW_VOLUME:
890     return "NEW_VOLUME";
891   case NEW_VOLUMETRIC_MODEL:
892     return "NEW_VOLUMETRIC_MODEL";
893   case NEW_CAMERA:
894     return "NEW_CAMERA";
895   case NEW_TRANSFER_FUNCTION:
896     return "NEW_TRANSFER_FUNCTION";
897   case NEW_IMAGE_OPERATION:
898     return "NEW_IMAGE_OPERATION";
899   case NEW_MATERIAL:
900     return "NEW_MATERIAL";
901   case NEW_LIGHT:
902     return "NEW_LIGHT";
903   case DATA_TRANSFER:
904     return "DATA_TRANSFER";
905   case NEW_SHARED_DATA:
906     return "NEW_SHARED_DATA";
907   case NEW_DATA:
908     return "NEW_DATA";
909   case COPY_DATA:
910     return "COPY_DATA";
911   case NEW_TEXTURE:
912     return "NEW_TEXTURE";
913   case NEW_GROUP:
914     return "NEW_GROUP";
915   case NEW_INSTANCE:
916     return "NEW_INSTANCE";
917   case COMMIT:
918     return "COMMIT";
919   case RELEASE:
920     return "RELEASE";
921   case RETAIN:
922     return "RETAIN";
923   case LOAD_MODULE:
924     return "LOAD_MODULE";
925   case CREATE_FRAMEBUFFER:
926     return "CREATE_FRAMEBUFFER";
927   case MAP_FRAMEBUFFER:
928     return "MAP_FRAMEBUFFER";
929   case GET_VARIANCE:
930     return "GET_VARIANCE";
931   case RESET_ACCUMULATION:
932     return "RESET_ACCUMULATION";
933   case RENDER_FRAME:
934     return "RENDER_FRAME";
935   case SET_PARAM:
936     return "SET_PARAM";
937   case REMOVE_PARAM:
938     return "REMOVE_PARAM";
939   case PICK:
940     return "PICK";
941   case GET_BOUNDS:
942     return "GET_BOUNDS";
943   case FUTURE_IS_READY:
944     return "FUTURE_IS_READY";
945   case FUTURE_WAIT:
946     return "FUTURE_WAIT";
947   case FUTURE_CANCEL:
948     return "FUTURE_CANCEL";
949   case FUTURE_GET_PROGRESS:
950     return "FUTURE_GET_PROGRESS";
951   case FINALIZE:
952     return "FINALIZE";
953   case NONE:
954   default:
955     return "NONE/UNKNOWN/INVALID";
956   }
957 }
958 
959 } // namespace work
960 } // namespace mpi
961 } // namespace ospray
962