예제 #1
0
 /*! finalize a newly specified model */
 void ISPCDevice::commit(OSPObject _object)
 {
   ManagedObject *object = (ManagedObject *)_object;
   object->commit();
 }
예제 #2
0
    /*! it's up to the proper init
      routine to decide which processes call this function and which
      ones don't. This function will not return. 
      
      \internal We ssume that mpi::worker and mpi::app have already been set up
    */
    void runWorker(int *_ac, const char **_av)
    {
      ospray::init(_ac,&_av);

      // initialize embree. (we need to do this here rather than in
      // ospray::init() because in mpi-mode the latter is also called
      // in the host-stubs, where it shouldn't.
      // std::stringstream embreeConfig;
      // if (debugMode)
      //   embreeConfig << " threads=1";
      // rtcInit(embreeConfig.str().c_str());

      //      assert(rtcGetError() == RTC_NO_ERROR);
      rtcSetErrorFunction(embreeErrorFunc);

      std::stringstream embreeConfig;
      if (debugMode)
        embreeConfig << " threads=1,verbose=2";
      rtcInit(embreeConfig.str().c_str());

      if (rtcGetError() != RTC_NO_ERROR) {
        // why did the error function not get called !?
        std::cerr << "#osp:init: embree internal error number " << (int)rtcGetError() << std::endl;
        assert(rtcGetError() == RTC_NO_ERROR);
      }


      CommandStream cmd;

      char hostname[HOST_NAME_MAX];
      gethostname(hostname,HOST_NAME_MAX);
      printf("#w: running MPI worker process %i/%i on pid %i@%s\n",
             worker.rank,worker.size,getpid(),hostname);
      int rc;


      // TiledLoadBalancer::instance = new mpi::DynamicLoadBalancer_Slave;
      TiledLoadBalancer::instance = new mpi::staticLoadBalancer::Slave;


      while (1) {
        const int command = cmd.get_int32();

        switch (command) {
        case api::MPIDevice::CMD_NEW_RENDERER: {
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new renderer \"" << type << "\" ID " << handle << endl;
          Renderer *renderer = Renderer::createRenderer(type);
          cmd.free(type);
          Assert(renderer);
          handle.assign(renderer);
        } break;
        case api::MPIDevice::CMD_NEW_CAMERA: {
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new camera \"" << type << "\" ID " << (void*)(int64)handle << endl;
          Camera *camera = Camera::createCamera(type);
          cmd.free(type);
          Assert(camera);
          handle.assign(camera);
          //          cout << "#w: new camera " << handle << endl;
        } break;
        case api::MPIDevice::CMD_NEW_VOLUME: {
          // Assert(type != NULL && "invalid volume type identifier");
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new volume \"" << type << "\" ID " << (void*)(int64)handle << endl;
          Volume *volume = Volume::createInstance(type);
          if (!volume) 
            throw std::runtime_error("unknown volume type '"+std::string(type)+"'");
          volume->refInc();
          cmd.free(type);
          Assert(volume);
          handle.assign(volume);
          //          cout << "#w: new volume " << handle << endl;
        } break;
        case api::MPIDevice::CMD_NEW_TRANSFERFUNCTION: {
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new transfer function \"" << type << "\" ID " << (void*)(int64)handle << endl;
          TransferFunction *transferFunction = TransferFunction::createInstance(type);
          if (!transferFunction) {
            throw std::runtime_error("unknown transfer function type '"+std::string(type)+"'");
          }
          transferFunction->refInc();
          cmd.free(type);
          handle.assign(transferFunction);
        } break;
        case api::MPIDevice::CMD_NEW_MATERIAL: {
          // Assert(type != NULL && "invalid volume type identifier");
          const mpi::Handle rendererHandle = cmd.get_handle();
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new material \"" << type << "\" ID " << (void*)(int64)handle << endl;

          Renderer *renderer = (Renderer *)rendererHandle.lookup();
          Material *material = NULL;
          if (renderer) {
            material = renderer->createMaterial(type);
            if (material) {
              material->refInc();
            }
          }
          if (material == NULL) 
            // no renderer present, or renderer didn't intercept this material.
            material = Material::createMaterial(type);
          
          int myFail = (material == NULL);
          int sumFail = 0;
          rc = MPI_Allreduce(&myFail,&sumFail,1,MPI_INT,MPI_SUM,worker.comm);
          if (sumFail == 0) {
            material->refInc();
            cmd.free(type);
            Assert(material);
            handle.assign(material);
            if (worker.rank == 0) {
              if (logLevel > 2)
                cout << "#w: new material " << handle << " " 
                     << material->toString() << endl;
              MPI_Send(&sumFail,1,MPI_INT,0,0,mpi::app.comm);
            }
          } else { 
            // at least one client could not load/create material ...
            if (material) material->refDec();
            if (worker.rank == 0) {
              if (logLevel > 2)
                cout << "#w: could not create material " << handle << " " 
                     << material->toString() << endl;
              MPI_Send(&sumFail,1,MPI_INT,0,0,mpi::app.comm);
            }
          }
        } break;

        case api::MPIDevice::CMD_NEW_LIGHT: {
          const mpi::Handle rendererHandle = cmd.get_handle();
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new light \"" << type << "\" ID " << (void*)(int64)handle << endl;

          Renderer *renderer = (Renderer *)rendererHandle.lookup();
          Light *light = NULL;
          if (renderer) {
            light = renderer->createLight(type);
            if (light) {
              light->refInc();
            }
          }
          if (light == NULL) 
            // no renderer present, or renderer didn't intercept this light.
            light = Light::createLight(type);

          int myFail = (light == NULL);
          int sumFail = 0;
          rc = MPI_Allreduce(&myFail,&sumFail,1,MPI_INT,MPI_SUM,worker.comm);
          if (sumFail == 0) {
            light->refInc();
            cmd.free(type);
            Assert(light);
            handle.assign(light);
            if (worker.rank == 0) {
              if (logLevel > 2)
                cout << "#w: new light " << handle << " " 
                     << light->toString() << endl;
              MPI_Send(&sumFail,1,MPI_INT,0,0,mpi::app.comm);
            }
          } else { 
            // at least one client could not load/create light ...
            if (light) light->refDec();
            if (worker.rank == 0) {
              if (logLevel > 2)
                cout << "#w: could not create light " << handle << " " 
                     << light->toString() << endl;
              MPI_Send(&sumFail,1,MPI_INT,0,0,mpi::app.comm);
            }
          }
        } break;

        case api::MPIDevice::CMD_NEW_GEOMETRY: {
          // Assert(type != NULL && "invalid volume type identifier");
          const mpi::Handle handle = cmd.get_handle();
          const char *type = cmd.get_charPtr();
          if (worker.rank == 0)
            if (logLevel > 2)
              cout << "creating new geometry \"" << type << "\" ID " << (void*)(int64)handle << endl;
          Geometry *geometry = Geometry::createGeometry(type);
          if (!geometry) 
            throw std::runtime_error("unknown geometry type '"+std::string(type)+"'");
          geometry->refInc();
          cmd.free(type);
          Assert(geometry);
          handle.assign(geometry);
          if (worker.rank == 0)
            if (logLevel > 2)
	      cout << "#w: new geometry " << handle << " " << geometry->toString() << endl;
        } break;

        case api::MPIDevice::CMD_FRAMEBUFFER_CREATE: {
          const mpi::Handle handle = cmd.get_handle();
          const vec2i  size               = cmd.get_vec2i();
          const OSPFrameBufferFormat mode = (OSPFrameBufferFormat)cmd.get_int32();
          const uint32 channelFlags       = cmd.get_int32();
          bool hasDepthBuffer = (channelFlags & OSP_FB_DEPTH);
          bool hasAccumBuffer = (channelFlags & OSP_FB_ACCUM);
          FrameBuffer *fb = new LocalFrameBuffer(size,mode,hasDepthBuffer,hasAccumBuffer);
          handle.assign(fb);
        } break;
        case api::MPIDevice::CMD_FRAMEBUFFER_CLEAR: {
          const mpi::Handle handle = cmd.get_handle();
          const uint32 channelFlags       = cmd.get_int32();
          FrameBuffer *fb = (FrameBuffer*)handle.lookup();
          fb->clear(channelFlags);
        } break;
        case api::MPIDevice::CMD_RENDER_FRAME: {
          const mpi::Handle  fbHandle = cmd.get_handle();
          // const mpi::Handle  swapChainHandle = cmd.get_handle();
          const mpi::Handle  rendererHandle  = cmd.get_handle();
          const uint32 channelFlags          = cmd.get_int32();
          FrameBuffer *fb = (FrameBuffer*)fbHandle.lookup();
          // SwapChain *sc = (SwapChain*)swapChainHandle.lookup();
          // Assert(sc);
          Renderer *renderer = (Renderer*)rendererHandle.lookup();
          Assert(renderer);
          renderer->renderFrame(fb,channelFlags); //sc->getBackBuffer());
          // sc->advance();
        } break;
        case api::MPIDevice::CMD_FRAMEBUFFER_MAP: {
          FATAL("should never get called on worker!?");
          // const mpi::Handle handle = cmd.get_handle();
          // FrameBuffer *fb = (FrameBuffer*)handle.lookup();
          // // SwapChain *sc = (SwapChain*)handle.lookup();
          // // Assert(sc);
          // if (worker.rank == 0) {
          //   // FrameBuffer *fb = sc->getBackBuffer();
          //   void *ptr = (void*)fb->map();
          //   // void *ptr = (void*)sc->map();
          //   rc = MPI_Send(ptr,fb->size.x*fb->size.y,MPI_INT,0,0,mpi::app.comm);
          //   Assert(rc == MPI_SUCCESS);
          //   fb->unmap(ptr);
          // }
        } break;
        case api::MPIDevice::CMD_NEW_MODEL: {
          const mpi::Handle handle = cmd.get_handle();
          Model *model = new Model;
          Assert(model);
          handle.assign(model);
          if (logLevel > 2)
            cout << "#w: new model " << handle << endl;
        } break;
        case api::MPIDevice::CMD_NEW_TRIANGLEMESH: {
          const mpi::Handle handle = cmd.get_handle();
          TriangleMesh *triangleMesh = new TriangleMesh;
          Assert(triangleMesh);
          handle.assign(triangleMesh);
        } break;
        case api::MPIDevice::CMD_NEW_DATA: {
          const mpi::Handle handle = cmd.get_handle();
          Data *data = NULL;
          size_t nitems      = cmd.get_size_t();
          OSPDataType format = (OSPDataType)cmd.get_int32();
          int flags          = cmd.get_int32();
          data = new Data(nitems,format,NULL,flags & ~OSP_DATA_SHARED_BUFFER);
          Assert(data);
          handle.assign(data);

          size_t hasInitData = cmd.get_size_t();
          if (hasInitData) {
            cmd.get_data(nitems*sizeOf(format),data->data);
            if (format==OSP_OBJECT) {
              /* translating handles to managedobject pointers: if a
                 data array has 'object' or 'data' entry types, then
                 what the host sends are _handles_, not pointers, but
                 what the core expects are pointers; to make the core
                 happy we translate all data items back to pointers at
                 this stage */
              mpi::Handle    *asHandle = (mpi::Handle    *)data->data;
              ManagedObject **asObjPtr = (ManagedObject **)data->data;
              for (int i=0;i<nitems;i++) {
                if (asHandle[i] != NULL_HANDLE) {
                  asObjPtr[i] = asHandle[i].lookup();
                  asObjPtr[i]->refInc();
                }
              }
            }
          }
        } break;

        case api::MPIDevice::CMD_NEW_TEXTURE2D: {
          const mpi::Handle handle = cmd.get_handle();
          Texture2D *texture2D = NULL;

          int32 width = cmd.get_int32();
          int32 height = cmd.get_int32();
          int32 type = cmd.get_int32();
          int32 flags = cmd.get_int32();
          size_t size = cmd.get_size_t();
          
          void *data = malloc(size);
          cmd.get_data(size,data);

          texture2D = Texture2D::createTexture(width,height,(OSPDataType)type,data,flags);
          assert(texture2D);
          handle.assign(texture2D);
        } break;

        case api::MPIDevice::CMD_ADD_GEOMETRY: {
          const mpi::Handle modelHandle = cmd.get_handle();
          const mpi::Handle geomHandle = cmd.get_handle();
          Model *model = (Model*)modelHandle.lookup();
          Assert(model);
          Geometry *geom = (Geometry*)geomHandle.lookup();
          Assert(geom);
          model->geometry.push_back(geom);
        } break;

        case api::MPIDevice::CMD_ADD_VOLUME: {
          const mpi::Handle modelHandle = cmd.get_handle();
          const mpi::Handle volumeHandle = cmd.get_handle();
          Model *model = (Model *) modelHandle.lookup();
          Assert(model);
          Volume *volume = (Volume *) volumeHandle.lookup();
          Assert(volume);
          model->volumes.push_back(volume);
        } break;

        case api::MPIDevice::CMD_COMMIT: {
          const mpi::Handle handle = cmd.get_handle();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          // printf("#w%i:c%i obj %lx\n",worker.rank,(int)handle,obj);
          if (logLevel > 2)
            cout << "#w: committing " << handle << " " << obj->toString() << endl;
          obj->commit();

          // hack, to stay compatible with earlier version
          Model *model = dynamic_cast<Model *>(obj);
          if (model)
            model->finalize();
        } break;
        case api::MPIDevice::CMD_SET_OBJECT: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const mpi::Handle val = cmd.get_handle();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->setParam(name,val.lookup());
          cmd.free(name);
        } break;
        case api::MPIDevice::CMD_RELEASE: {
          const mpi::Handle handle = cmd.get_handle();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          handle.freeObject();
        } break;
        case api::MPIDevice::CMD_SET_MATERIAL: {
          const mpi::Handle geoHandle = cmd.get_handle();
          const mpi::Handle matHandle = cmd.get_handle();
          Geometry *geo = (Geometry*)geoHandle.lookup();
          Material *mat = (Material*)matHandle.lookup();
          geo->setMaterial(mat);
        } break;
        case api::MPIDevice::CMD_SET_STRING: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const char *val  = cmd.get_charPtr();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->findParam(name,1)->set(val);
          cmd.free(name);
          cmd.free(val);
        } break;
        case api::MPIDevice::CMD_SET_INT: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const int val = cmd.get_int();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->findParam(name,1)->set(val);
          cmd.free(name);
        } break;
        case api::MPIDevice::CMD_SET_FLOAT: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const float val = cmd.get_float();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->findParam(name,1)->set(val);
          cmd.free(name);
        } break;
        case api::MPIDevice::CMD_SET_VEC3F: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const vec3f val = cmd.get_vec3f();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->findParam(name,1)->set(val);
          cmd.free(name);
        } break;
        case api::MPIDevice::CMD_SET_VEC2F: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const vec2f val = cmd.get_vec2f();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->findParam(name,1)->set(val);
          cmd.free(name);
        } break;
        case api::MPIDevice::CMD_SET_VEC3I: {
          const mpi::Handle handle = cmd.get_handle();
          const char *name = cmd.get_charPtr();
          const vec3i val = cmd.get_vec3i();
          ManagedObject *obj = handle.lookup();
          Assert(obj);
          obj->findParam(name,1)->set(val);
          cmd.free(name);
        } break;
        case api::MPIDevice::CMD_LOAD_MODULE: {
          const char *name = cmd.get_charPtr();

#if THIS_IS_MIC
          // embree automatically puts this into "lib<name>.so" format
          std::string libName = "ospray_module_"+std::string(name)+"_mic";
#else
          std::string libName = "ospray_module_"+std::string(name)+"";
#endif
          loadLibrary(libName);
      
          std::string initSymName = "ospray_init_module_"+std::string(name);
          void*initSym = getSymbol(initSymName);
          if (!initSym)
            throw std::runtime_error("could not find module initializer "+initSymName);
          void (*initMethod)() = (void(*)())initSym;
          initMethod();

          cmd.free(name);
        } break;
        default: 
          std::stringstream err;
          err << "unknown cmd tag " << command;
          throw std::runtime_error(err.str());
        }
      };
    }