int main (int argc, const char *argv[]) { Timer timer; // Create a new shading system. We pass it the RendererServices // object that services callbacks from the shading system, NULL for // the TextureSystem (which will create a default OIIO one), and // an error handler. shadingsys = new ShadingSystem (&rend, NULL, &errhandler); // Register the layout of all closures known to this renderer // Any closure used by the shader which is not registered, or // registered with a different number of arguments will lead // to a runtime error. register_closures(shadingsys); // Remember that each shader parameter may optionally have a // metadata hint [[int lockgeom=...]], where 0 indicates that the // parameter may be overridden by the geometry itself, for example // with data interpolated from the mesh vertices, and a value of 1 // means that it is "locked" with respect to the geometry (i.e. it // will not be overridden with interpolated or // per-geometric-primitive data). // // In order to most fully optimize shader, we typically want any // shader parameter not explicitly specified to default to being // locked (i.e. no per-geometry override): shadingsys->attribute("lockgeom", 1); // Read command line arguments getargs (argc, argv); // Setup common attributes shadingsys->attribute ("debug", debug2 ? 2 : (debug ? 1 : 0)); shadingsys->attribute ("compile_report", debug|debug2); const char *opt_env = getenv ("TESTSHADE_OPT"); // overrides opt if (opt_env) shadingsys->attribute ("optimize", atoi(opt_env)); else if (O0 || O1 || O2) shadingsys->attribute ("optimize", O2 ? 2 : (O1 ? 1 : 0)); shadingsys->attribute ("debugnan", debugnan); // Loads a scene, creating camera, geometry and assigning shaders parse_scene(); // validate options if (aa < 1) aa = 1; if (num_threads < 1) num_threads = boost::thread::hardware_concurrency(); // prepare background importance table (if requested) if (backgroundResolution > 0 && backgroundShaderID >= 0) { // get a context so we can make several background shader calls OSL::PerThreadInfo *thread_info = shadingsys->create_thread_info(); ShadingContext *ctx = shadingsys->get_context (thread_info); // build importance table to optimize background sampling background.prepare(backgroundResolution, eval_background, ctx); // release context shadingsys->release_context (ctx); shadingsys->destroy_thread_info(thread_info); } else { // we aren't directly evaluating the background backgroundResolution = 0; } double setuptime = timer.lap (); std::vector<Color3> pixels(xres * yres, Color3(0,0,0)); // Create shared counter to iterate over one scanline at a time Counter scanline_counter(errhandler, yres, "Rendering"); // launch a scanline worker for each thread boost::thread_group workers; for (int i = 0; i < num_threads; i++) workers.add_thread(new boost::thread(scanline_worker, boost::ref(scanline_counter), boost::ref(pixels))); workers.join_all(); // Write image to disk ImageOutput* out = ImageOutput::create(imagefile); ImageSpec spec(xres, yres, 3, TypeDesc::HALF); if (out && out->open(imagefile, spec)) { out->write_image(TypeDesc::TypeFloat, &pixels[0]); } else { errhandler.error("Unable to write output image"); } delete out; // Print some debugging info if (debug || stats) { double runtime = timer.lap(); std::cout << "\n"; std::cout << "Setup: " << OIIO::Strutil::timeintervalformat (setuptime,2) << "\n"; std::cout << "Run : " << OIIO::Strutil::timeintervalformat (runtime,2) << "\n"; std::cout << "\n"; std::cout << shadingsys->getstats (5) << "\n"; OIIO::TextureSystem *texturesys = shadingsys->texturesys(); if (texturesys) std::cout << texturesys->getstats (5) << "\n"; std::cout << ustring::getstats() << "\n"; } // We're done with the shading system now, destroy it shaders.clear (); // Must release the group refs first delete shadingsys; return EXIT_SUCCESS; }
extern "C" OSL_DLL_EXPORT int test_shade (int argc, const char *argv[]) { OIIO::Timer timer; // Create a new shading system. We pass it the RendererServices // object that services callbacks from the shading system, NULL for // the TextureSystem (that just makes 'create' make its own TS), and // an error handler. shadingsys = new ShadingSystem (&rend, NULL, &errhandler); // Register the layout of all closures known to this renderer // Any closure used by the shader which is not registered, or // registered with a different number of arguments will lead // to a runtime error. register_closures(shadingsys); // Remember that each shader parameter may optionally have a // metadata hint [[int lockgeom=...]], where 0 indicates that the // parameter may be overridden by the geometry itself, for example // with data interpolated from the mesh vertices, and a value of 1 // means that it is "locked" with respect to the geometry (i.e. it // will not be overridden with interpolated or // per-geometric-primitive data). // // In order to most fully optimize shader, we typically want any // shader parameter not explicitly specified to default to being // locked (i.e. no per-geometry override): shadingsys->attribute("lockgeom", 1); // Now we declare our shader. // // Each material in the scene is comprised of a "shader group." // Each group is comprised of one or more "layers" (a.k.a. shader // instances) with possible connections from outputs of // upstream/early layers into the inputs of downstream/later layers. // A shader instance is the combination of a reference to a shader // master and its parameter values that may override the defaults in // the shader source and may be particular to this instance (versus // all the other instances of the same shader). // // A shader group declaration typically looks like this: // // ShaderGroupRef shadergroup = ss->ShaderGroupBegin (); // ss->Parameter ("paramname", TypeDesc paramtype, void *value); // ... and so on for all the other parameters of... // ss->Shader ("shadertype", "shadername", "layername"); // The Shader() call creates a new instance, which gets // all the pending Parameter() values made right before it. // ... and other shader instances in this group, interspersed with... // ss->ConnectShaders ("layer1", "param1", "layer2", "param2"); // ... and other connections ... // ss->ShaderGroupEnd (); // // It looks so simple, and it really is, except that the way this // testshade program works is that all the Parameter() and Shader() // calls are done inside getargs(), as it walks through the command // line arguments, whereas the connections accumulate and have // to be processed at the end. Bear with us. // Start the shader group and grab a reference to it. shadergroup = shadingsys->ShaderGroupBegin (groupname); // Get the command line arguments. That will set up all the shader // instances and their parameters for the group. getargs (argc, argv); if (! shadergroup) { std::cerr << "ERROR: Invalid shader group. Exiting testshade.\n"; return EXIT_FAILURE; } shadingsys->attribute (shadergroup.get(), "groupname", groupname); // Now set up the connections for (size_t i = 0; i < connections.size(); i += 4) { if (i+3 < connections.size()) { std::cout << "Connect " << connections[i] << "." << connections[i+1] << " to " << connections[i+2] << "." << connections[i+3] << "\n"; shadingsys->ConnectShaders (connections[i].c_str(), connections[i+1].c_str(), connections[i+2].c_str(), connections[i+3].c_str()); } } // End the group shadingsys->ShaderGroupEnd (); if (verbose || do_oslquery) { std::string pickle; shadingsys->getattribute (shadergroup.get(), "pickle", pickle); std::cout << "Shader group:\n---\n" << pickle << "\n---\n"; std::cout << "\n"; ustring groupname; shadingsys->getattribute (shadergroup.get(), "groupname", groupname); std::cout << "Shader group \"" << groupname << "\" layers are:\n"; int num_layers = 0; shadingsys->getattribute (shadergroup.get(), "num_layers", num_layers); if (num_layers > 0) { std::vector<const char *> layers (size_t(num_layers), NULL); shadingsys->getattribute (shadergroup.get(), "layer_names", TypeDesc(TypeDesc::STRING, num_layers), &layers[0]); for (int i = 0; i < num_layers; ++i) { std::cout << " " << (layers[i] ? layers[i] : "<unnamed>") << "\n"; if (do_oslquery) { OSLQuery q; q.init (shadergroup.get(), i); for (size_t p = 0; p < q.nparams(); ++p) { const OSLQuery::Parameter *param = q.getparam(p); std::cout << "\t" << (param->isoutput ? "output " : "") << param->type << ' ' << param->name << "\n"; } } } } std::cout << "\n"; } if (archivegroup.size()) shadingsys->archive_shadergroup (shadergroup.get(), archivegroup); if (outputfiles.size() != 0) std::cout << "\n"; // Set up the named transformations, including shader and object. // For this test application, we just do this statically; in a real // renderer, the global named space (like "myspace") would probably // be static, but shader and object spaces may be different for each // object. setup_transformations (rend, Mshad, Mobj); // Set up the image outputs requested on the command line setup_output_images (shadingsys, shadergroup); if (debug) test_group_attributes (shadergroup.get()); if (num_threads < 1) num_threads = boost::thread::hardware_concurrency(); double setuptime = timer.lap (); // Allow a settable number of iterations to "render" the whole image, // which is useful for time trials of things that would be too quick // to accurately time for a single iteration for (int iter = 0; iter < iters; ++iter) { OIIO::ROI roi (0, xres, 0, yres); if (use_shade_image) OSL::shade_image (*shadingsys, *shadergroup, NULL, *outputimgs[0], outputvarnames, pixelcenters ? ShadePixelCenters : ShadePixelGrid, roi, num_threads); else { bool save = (iter == (iters-1)); // save on last iteration #if 0 shade_region (shadergroup.get(), roi, save); #else OIIO::ImageBufAlgo::parallel_image ( boost::bind (shade_region, shadergroup.get(), _1, save), roi, num_threads); #endif } // If any reparam was requested, do it now if (reparams.size() && reparam_layer.size()) { for (size_t p = 0; p < reparams.size(); ++p) { const ParamValue &pv (reparams[p]); shadingsys->ReParameter (*shadergroup, reparam_layer.c_str(), pv.name().c_str(), pv.type(), pv.data()); } } } double runtime = timer.lap(); if (outputfiles.size() == 0) std::cout << "\n"; // Write the output images to disk for (size_t i = 0; i < outputimgs.size(); ++i) { if (outputimgs[i]) { if (! print_outputs) { std::string filename = outputimgs[i]->name(); // JPEG, GIF, and PNG images should be automatically saved // as sRGB because they are almost certainly supposed to // be displayed on web pages. using namespace OIIO; if (Strutil::iends_with (filename, ".jpg") || Strutil::iends_with (filename, ".jpeg") || Strutil::iends_with (filename, ".gif") || Strutil::iends_with (filename, ".png")) { ImageBuf ccbuf; ImageBufAlgo::colorconvert (ccbuf, *outputimgs[i], "linear", "sRGB", false, "", ""); ccbuf.set_write_format (outputimgs[i]->spec().format); ccbuf.write (filename); } else { outputimgs[i]->write (filename); } } delete outputimgs[i]; outputimgs[i] = NULL; } } // Print some debugging info if (debug || runstats || profile) { double writetime = timer.lap(); std::cout << "\n"; std::cout << "Setup: " << OIIO::Strutil::timeintervalformat (setuptime,2) << "\n"; std::cout << "Run : " << OIIO::Strutil::timeintervalformat (runtime,2) << "\n"; std::cout << "Write: " << OIIO::Strutil::timeintervalformat (writetime,2) << "\n"; std::cout << "\n"; std::cout << shadingsys->getstats (5) << "\n"; OIIO::TextureSystem *texturesys = shadingsys->texturesys(); if (texturesys) std::cout << texturesys->getstats (5) << "\n"; std::cout << ustring::getstats() << "\n"; } // We're done with the shading system now, destroy it shadergroup.reset (); // Must release this before destroying shadingsys delete shadingsys; return EXIT_SUCCESS; }
int main (int argc, const char *argv[]) { try { using namespace OIIO; Timer timer; // Read command line arguments getargs (argc, argv); SimpleRaytracer *rend = nullptr; if (use_optix) rend = new OptixRaytracer; else rend = new SimpleRaytracer; // Other renderer and global options if (debug1 || verbose) rend->errhandler().verbosity (ErrorHandler::VERBOSE); rend->attribute("saveptx", (int)saveptx); rend->attribute("max_bounces", max_bounces); rend->attribute("rr_depth", rr_depth); rend->attribute("aa", aa); OIIO::attribute("threads", num_threads); // Create a new shading system. We pass it the RendererServices // object that services callbacks from the shading system, the // TextureSystem (note: passing nullptr just makes the ShadingSystem // make its own TS), and an error handler. shadingsys = new ShadingSystem (rend, nullptr, &rend->errhandler()); rend->shadingsys = shadingsys; // Register the layout of all closures known to this renderer // Any closure used by the shader which is not registered, or // registered with a different number of arguments will lead // to a runtime error. register_closures(shadingsys); // Setup common attributes set_shadingsys_options(); // Loads a scene, creating camera, geometry and assigning shaders rend->camera.resolution (xres, yres); rend->parse_scene_xml (scenefile); rend->prepare_render (); rend->pixelbuf.reset (ImageSpec(xres, yres, 3, TypeDesc::FLOAT)); double setuptime = timer.lap (); if (warmup) rend->warmup(); double warmuptime = timer.lap (); // Launch the kernel to render the scene for (int i = 0; i < iters; ++i) rend->render (xres, yres); double runtime = timer.lap (); rend->finalize_pixel_buffer (); // Write image to disk if (Strutil::iends_with (imagefile, ".jpg") || Strutil::iends_with (imagefile, ".jpeg") || Strutil::iends_with (imagefile, ".gif") || Strutil::iends_with (imagefile, ".png")) { // JPEG, GIF, and PNG images should be automatically saved as sRGB // because they are almost certainly supposed to be displayed on web // pages. ImageBufAlgo::colorconvert (rend->pixelbuf, rend->pixelbuf, "linear", "sRGB", false, "", ""); } rend->pixelbuf.set_write_format (TypeDesc::HALF); if (! rend->pixelbuf.write (imagefile)) rend->errhandler().error ("Unable to write output image: %s", rend->pixelbuf.geterror()); double writetime = timer.lap(); // Print some debugging info if (debug1 || runstats || profile) { std::cout << "\n"; std::cout << "Setup : " << OIIO::Strutil::timeintervalformat (setuptime,4) << "\n"; std::cout << "Warmup: " << OIIO::Strutil::timeintervalformat (warmuptime,4) << "\n"; std::cout << "Run : " << OIIO::Strutil::timeintervalformat (runtime,4) << "\n"; std::cout << "Write : " << OIIO::Strutil::timeintervalformat (writetime,4) << "\n"; std::cout << "\n"; std::cout << shadingsys->getstats (5) << "\n"; OIIO::TextureSystem *texturesys = shadingsys->texturesys(); if (texturesys) std::cout << texturesys->getstats (5) << "\n"; std::cout << ustring::getstats() << "\n"; } // We're done with the shading system now, destroy it rend->clear(); delete shadingsys; delete rend; } catch (const optix::Exception& e) { printf("Optix Error: %s\n", e.what()); } catch (const std::exception& e) { printf("Unknown Error: %s\n", e.what()); } return EXIT_SUCCESS; }
extern "C" int test_shade (int argc, const char *argv[]) { OIIO::Timer timer; // Create a new shading system. We pass it the RendererServices // object that services callbacks from the shading system, NULL for // the TextureSystem (that just makes 'create' make its own TS), and // an error handler. shadingsys = new ShadingSystem (&rend, NULL, &errhandler); register_closures(shadingsys); // Remember that each shader parameter may optionally have a // metadata hint [[int lockgeom=...]], where 0 indicates that the // parameter may be overridden by the geometry itself, for example // with data interpolated from the mesh vertices, and a value of 1 // means that it is "locked" with respect to the geometry (i.e. it // will not be overridden with interpolated or // per-geometric-primitive data). // // In order to most fully optimize shader, we typically want any // shader parameter not explicitly specified to default to being // locked (i.e. no per-geometry override): shadingsys->attribute("lockgeom", 1); // Now we declare our shader. // // Each material in the scene is comprised of a "shader group." // Each group is comprised of one or more "layers" (a.k.a. shader // instances) with possible connections from outputs of // upstream/early layers into the inputs of downstream/later layers. // A shader instance is the combination of a reference to a shader // master and its parameter values that may override the defaults in // the shader source and may be particular to this instance (versus // all the other instances of the same shader). // // A shader group declaration typically looks like this: // // ShaderGroupRef shadergroup = ss->ShaderGroupBegin (); // ss->Parameter ("paramname", TypeDesc paramtype, void *value); // ... and so on for all the other parameters of... // ss->Shader ("shadertype", "shadername", "layername"); // The Shader() call creates a new instance, which gets // all the pending Parameter() values made right before it. // ... and other shader instances in this group, interspersed with... // ss->ConnectShaders ("layer1", "param1", "layer2", "param2"); // ... and other connections ... // ss->ShaderGroupEnd (); // // It looks so simple, and it really is, except that the way this // testshade program works is that all the Parameter() and Shader() // calls are done inside getargs(), as it walks through the command // line arguments, whereas the connections accumulate and have // to be processed at the end. Bear with us. // Start the shader group and grab a reference to it. ShaderGroupRef shadergroup = shadingsys->ShaderGroupBegin (); // Get the command line arguments. That will set up all the shader // instances and their parameters for the group. getargs (argc, argv); // Now set up the connections for (size_t i = 0; i < connections.size(); i += 4) { if (i+3 < connections.size()) { std::cout << "Connect " << connections[i] << "." << connections[i+1] << " to " << connections[i+2] << "." << connections[i+3] << "\n"; shadingsys->ConnectShaders (connections[i].c_str(), connections[i+1].c_str(), connections[i+2].c_str(), connections[i+3].c_str()); } } // End the group shadingsys->ShaderGroupEnd (); if (outputfiles.size() != 0) std::cout << "\n"; // Set up the named transformations, including shader and object. // For this test application, we just do this statically; in a real // renderer, the global named space (like "myspace") would probably // be static, but shader and object spaces may be different for each // object. setup_transformations (rend, Mshad, Mobj); // Set up the image outputs requested on the command line setup_output_images (shadingsys, shadergroup); if (debug) test_group_attributes (shadergroup.get()); if (num_threads < 1) num_threads = boost::thread::hardware_concurrency(); double setuptime = timer.lap (); // Allow a settable number of iterations to "render" the whole image, // which is useful for time trials of things that would be too quick // to accurately time for a single iteration for (int iter = 0; iter < iters; ++iter) { OIIO::ROI roi (0, xres, 0, yres); bool save = (iter == (iters-1)); // save on last iteration #if 0 shade_region (shadergroup.get(), roi, save); #else OIIO::ImageBufAlgo::parallel_image ( boost::bind (shade_region, shadergroup.get(), _1, save), roi, num_threads); #endif // If any reparam was requested, do it now if (reparams.size() && reparam_layer.size()) { for (size_t p = 0; p < reparams.size(); ++p) { const ParamValue &pv (reparams[p]); shadingsys->ReParameter (*shadergroup, reparam_layer.c_str(), pv.name().c_str(), pv.type(), pv.data()); } } } if (outputfiles.size() == 0) std::cout << "\n"; // Write the output images to disk for (size_t i = 0; i < outputimgs.size(); ++i) { if (outputimgs[i]) { outputimgs[i]->save(); delete outputimgs[i]; outputimgs[i] = NULL; } } // Print some debugging info if (debug || stats) { double runtime = timer.lap(); std::cout << "\n"; std::cout << "Setup: " << OIIO::Strutil::timeintervalformat (setuptime,2) << "\n"; std::cout << "Run : " << OIIO::Strutil::timeintervalformat (runtime,2) << "\n"; std::cout << "\n"; std::cout << shadingsys->getstats (5) << "\n"; OIIO::TextureSystem *texturesys = shadingsys->texturesys(); if (texturesys) std::cout << texturesys->getstats (5) << "\n"; std::cout << ustring::getstats() << "\n"; } // We're done with the shading system now, destroy it shadergroup.reset (); // Must release this before destroying shadingsys delete shadingsys; return EXIT_SUCCESS; }
void CoronaRenderer::render() { Logging::debug("CoronaRenderer::render"); Corona::LicenseInfo li = Corona::ICore::getLicenseInfo(); if (!li.isUsable()) { MString reason = li.error.cStr(); MGlobal::displayError(MString("Sorry! Could not get a valid license.") + reason); return; } context.scene = context.core->createScene(); //createTestScene(); //OSL::OSLShadingNetworkRenderer *r = new OSL::OSLShadingNetworkRenderer(); // set this value here. In case we have a swatch rendering ongoing, we have to make sure that the correct osl renderer is used. MayaTo::getWorldPtr()->setRenderType(MayaTo::MayaToWorld::WorldRenderType::UIRENDER); //this->clearMaterialLists(); this->defineCamera(); this->defineGeometry(); this->defineEnvironment(); this->defineLights(); context.core->sanityCheck(context.scene); Logging::debug(MString("registering framebuffer callback.")); Corona::String basePath = (MayaTo::getWorldPtr()->worldRenderGlobalsPtr->basePath + "/corona/").asChar(); Logging::debug(MString("beginSession...")); ICore::AdditionalInfo info; info.defaultFilePath = basePath; context.core->beginSession(context.scene, context.settings, context.fb, context.logger, info); int maxCount=100, count=0; MayaTo::MayaToWorld::WorldRenderState st = MayaTo::getWorldPtr()->getRenderState(); while (st == MayaTo::MayaToWorld::WorldRenderState::RSTATESWATCHRENDERING) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); count++; if (count >= maxCount) { Logging::warning("WorldRenderState is RSTATERENDERING, but wait is over..."); break; } st = MayaTo::getWorldPtr()->getRenderState(); } MayaTo::getWorldPtr()->setRenderState(MayaTo::MayaToWorld::WorldRenderState::RSTATERENDERING); size_t framebufferCallbackId = RenderQueueWorker::registerCallback(&framebufferCallback); context.core->renderFrame(); // blocking render call context.core->endSession(); RenderQueueWorker::unregisterCallback(framebufferCallbackId); framebufferCallback(); this->saveImage(); //std::string statsString = this->oslRenderer->shadingsys->getstats(); //Logging::debug(statsString.c_str()); OIIO::TextureSystem *tsystem = this->oslRenderer->renderer.texturesys(); std::string statsString = tsystem->getstats(3); Logging::debug(statsString.c_str()); MayaTo::getWorldPtr()->setRenderState(MayaTo::MayaToWorld::WorldRenderState::RSTATENONE); // it is simpler to remove the data completly than to update single elements at the moment. if (context.scene != nullptr) { context.core->destroyScene(context.scene); context.scene = nullptr; } MFnDependencyNode gFn(getRenderGlobalsNode()); if (gFn.findPlug("useCoronaVFB").asBool()) if (MGlobal::mayaState() != MGlobal::kBatch) context.core->getWxVfb().renderFinished(); }