static int BatchSimpleMode(const double haltTime, const unsigned int haltSpp, const float haltThreshold) { RenderConfig *config = session->renderConfig; RenderEngine *engine = session->renderEngine; // Force the film update at 2.5secs (mostly used by PathOCL) config->SetScreenRefreshInterval(2500); // Start the rendering session->Start(); // Nothing to do if it is the FileSaverRenderEngine if (!dynamic_cast<FileSaverRenderEngine *>(engine)) { const double startTime = WallClockTime(); double lastFilmUpdate = WallClockTime(); char buf[512]; for (;;) { boost::this_thread::sleep(boost::posix_time::millisec(1000)); // Check if periodic save is enabled if (session->NeedPeriodicSave()) { // Time to save the image and film session->SaveFilmImage(); lastFilmUpdate = WallClockTime(); } else { // Film update may be required by some render engine to // update statistics, convergence test and more if (WallClockTime() - lastFilmUpdate > 5.0) { session->renderEngine->UpdateFilm(); lastFilmUpdate = WallClockTime(); } } const double now = WallClockTime(); const double elapsedTime = now - startTime; if ((haltTime > 0) && (elapsedTime >= haltTime)) break; const unsigned int pass = engine->GetPass(); if ((haltSpp > 0) && (pass >= haltSpp)) break; // Convergence test is update inside UpdateFilm() const float convergence = engine->GetConvergence(); if ((haltThreshold >= 0.f) && (1.f - convergence <= haltThreshold)) break; // Print some information about the rendering progress sprintf(buf, "[Elapsed time: %3d/%dsec][Samples %4d/%d][Convergence %f%%][Avg. samples/sec % 3.2fM on %.1fK tris]", int(elapsedTime), int(haltTime), pass, haltSpp, 100.f * convergence, engine->GetTotalSamplesSec() / 1000000.0, config->scene->dataSet->GetTotalTriangleCount() / 1000.0); SLG_LOG(buf); } } // Stop the rendering session->Stop(); // Save the rendered image session->SaveFilmImage(); delete session; SLG_LOG("Done."); return EXIT_SUCCESS; }
static int BatchTileMode(const unsigned int haltSpp, const float haltThreshold) { RenderConfig *config = session->renderConfig; RenderEngine *engine = session->renderEngine; // batch.halttime condition doesn't make sense in the context // of tile rendering if (config->cfg.IsDefined("batch.halttime") && (config->cfg.GetInt("batch.halttime", 0) > 0)) throw runtime_error("batch.halttime parameter can not be used with batch.tile"); // image.subregion condition doesn't make sense in the context // of tile rendering if (config->cfg.IsDefined("image.subregion")) throw runtime_error("image.subregion parameter can not be used with batch.tile"); // Force the film update at 2.5secs (mostly used by PathOCL) config->SetScreenRefreshInterval(2500); const u_int filterBorder = 2; // Original film size const u_int originalFilmWidth = session->film->GetWidth(); const u_int originalFilmHeight = session->film->GetHeight(); // Allocate a film where to merge all tiles Film mergeTileFilm(originalFilmWidth, originalFilmWidth, session->film->HasPerPixelNormalizedBuffer(), session->film->HasPerScreenNormalizedBuffer(), true); mergeTileFilm.CopyDynamicSettings(*(session->film)); mergeTileFilm.EnableOverlappedScreenBufferUpdate(false); mergeTileFilm.Init(originalFilmWidth, originalFilmWidth); // Get the tile size vector<int> tileSize = config->cfg.GetIntVector("batch.tile", "256 256"); if (tileSize.size() != 2) throw runtime_error("Syntax error in batch.tile (required 2 parameters)"); tileSize[0] = Max<int>(64, Min<int>(tileSize[0], originalFilmWidth)); tileSize[1] = Max<int>(64, Min<int>(tileSize[1], originalFilmHeight)); SLG_LOG("Tile size: " << tileSize[0] << " x " << tileSize[1]); // Get the loop count int loopCount = config->cfg.GetInt("batch.tile.loops", 1); bool sessionStarted = false; for (int loopIndex = 0; loopIndex < loopCount; ++loopIndex) { u_int tileX = 0; u_int tileY = 0; const double startTime = WallClockTime(); // To setup new rendering parameters if (loopIndex > 0) { // I can begin an edit only after the start session->BeginEdit(); // I have to use a new seed or I will render exactly the same images session->renderEngine->GenerateNewSeed(); } for (;;) { SLG_LOG("Rendering tile offset: (" << tileX << "/" << originalFilmWidth + 2 * filterBorder << ", " << tileY << "/" << originalFilmHeight + 2 * filterBorder << ")"); // Set the film subregion to render u_int filmSubRegion[4]; filmSubRegion[0] = tileX; filmSubRegion[1] = Min(tileX + tileSize[0] - 1, originalFilmWidth - 1) + 2 * filterBorder; filmSubRegion[2] = tileY; filmSubRegion[3] = Min(tileY + tileSize[1] - 1, originalFilmHeight - 1) + 2 * filterBorder; SLG_LOG("Tile subregion: " << boost::lexical_cast<string>(filmSubRegion[0]) << " " << boost::lexical_cast<string>(filmSubRegion[1]) << " " << boost::lexical_cast<string>(filmSubRegion[2]) << " " << boost::lexical_cast<string>(filmSubRegion[3])); // Update the camera and resize the film session->renderConfig->scene->camera->Update( originalFilmWidth + 2 * filterBorder, originalFilmHeight + 2 * filterBorder, filmSubRegion); session->film->Init(session->renderConfig->scene->camera->GetFilmWeight(), session->renderConfig->scene->camera->GetFilmHeight()); if (sessionStarted) { session->editActions.AddAction(CAMERA_EDIT); session->editActions.AddAction(FILM_EDIT); session->EndEdit(); } else { session->Start(); sessionStarted = true; } double lastFilmUpdate = WallClockTime(); char buf[512]; for (;;) { boost::this_thread::sleep(boost::posix_time::millisec(1000)); // Film update may be required by some render engine to // update statistics, convergence test and more if (WallClockTime() - lastFilmUpdate > 5.0) { session->renderEngine->UpdateFilm(); lastFilmUpdate = WallClockTime(); } const unsigned int pass = engine->GetPass(); if ((haltSpp > 0) && (pass >= haltSpp)) break; // Convergence test is update inside UpdateFilm() const float convergence = engine->GetConvergence(); if ((haltThreshold >= 0.f) && (1.f - convergence <= haltThreshold)) break; // Print some information about the rendering progress const double now = WallClockTime(); const double elapsedTime = now - startTime; sprintf(buf, "[Loop step: %d/%d][Elapsed time: %3d][Samples %4d/%d][Convergence %f%%][Avg. samples/sec % 3.2fM on %.1fK tris]", loopIndex + 1, loopCount, int(elapsedTime), pass, haltSpp, 100.f * convergence, engine->GetTotalSamplesSec() / 1000000.0, config->scene->dataSet->GetTotalTriangleCount() / 1000.0); SLG_LOG(buf); } // Splat the current tile on the merge film session->renderEngine->UpdateFilm(); { boost::unique_lock<boost::mutex> lock(session->filmMutex); mergeTileFilm.AddFilm(*(session->film), filterBorder, filterBorder, filmSubRegion[1] - filmSubRegion[0] - 2 * filterBorder + 1, filmSubRegion[3] - filmSubRegion[2] - 2 * filterBorder + 1, tileX, tileY); } // Save the merge film const string fileName = config->cfg.GetString("image.filename", "image.png"); SLG_LOG("Saving merged tiles to: " << fileName); mergeTileFilm.UpdateScreenBuffer(); mergeTileFilm.SaveScreenBuffer(fileName); // Advance to the next tile tileX += tileSize[0]; if (tileX >= originalFilmWidth) { tileX = 0; tileY += tileSize[1]; if (tileY >= originalFilmHeight) { // Rendering done break; } } // To setup new rendering parameters session->BeginEdit(); } } // Stop the rendering session->Stop(); delete session; SLG_LOG("Done."); return EXIT_SUCCESS; }