TriangleTree * ABTreeBuilder::buildTriangleTree(Rendering::Mesh * mesh) { #ifdef MINSG_PROFILING std::cout << "Profiling: Creating ABTree(triangles=" << trianglesPerNode << ", enlargement=" << allowedBBEnlargement << ")" << std::endl; Util::Utils::outputProcessMemory(); Util::Timer timer; timer.reset(); #endif auto k = new ABTree(mesh, trianglesPerNode, allowedBBEnlargement); #ifdef MINSG_PROFILING timer.stop(); std::cout << "Profiling: Construction of root node: " << timer.getMilliseconds() << " ms" << std::endl; Util::Utils::outputProcessMemory(); timer.reset(); #endif if (k->shouldSplit()) { k->split(); } #ifdef MINSG_PROFILING timer.stop(); std::cout << "Profiling: Construction of tree structure: " << timer.getMilliseconds() << " ms" << std::endl; Util::Utils::outputProcessMemory(); #endif return k; }
int test_statistics() { std::ofstream output("test_statistics.tsv"); output << "class\tnumEventTypes\tnumEventsOverall\tduration\n"; Util::Timer timer; for(uint32_t numRuns = 1; numRuns < 5; ++numRuns) { for(uint32_t numEventsOverall = 1; numEventsOverall <= 1000000; numEventsOverall *= 10) { for(uint32_t numEventTypes = 1; numEventTypes <= 32; numEventTypes *= 2) { timer.reset(); testStatistics(numEventTypes, numEventsOverall); timer.stop(); output << "Statistics\t" << numEventTypes << '\t' << numEventsOverall << '\t' << timer.getNanoseconds() << '\n'; timer.reset(); testProfiler(numEventTypes, numEventsOverall); timer.stop(); output << "Profiler\t" << numEventTypes << '\t' << numEventsOverall << '\t' << timer.getNanoseconds() << '\n'; } } } return EXIT_SUCCESS; }
void Engine::setFPS(float dt) { static Util::Timer delay; static float sumDelta = 0.f; sumDelta += dt; if(!delay.running()) delay.start(); static std::ostringstream str; if(delay.isElapsed(200)) { str.str(""); str << "Trace Engine - " << (int)(1.f/dt) << " FPS"; renderSystem_->setWindowTitle(str.str().c_str()); str.str(""); str << (int)(1.f/dt); delay.stop(); } // fontRenderer_->renderText(str.str(), glm::vec3(10.f, 20.f, 50.f), "consola.ttf", glm::vec4(1.f, 1.f, 1.f, 1.f), 20); // fontRenderer_->renderText(Util::Str::formatTime(static_cast<int>(sumDelta)), glm::vec3(renderSystem_->resolution().x-100, 20.f, 50.f), "consola.ttf", glm::vec4(1.f, 1.f, 1.f, 1.f), 20); }
/*! * \brief Constructor * \param procedure Procedure to analyze */ LiveVariables::LiveVariables(const IR::Procedure &procedure, const FlowGraph &flowGraph) : mProcedure(procedure) { Util::Timer timer; timer.start(); // Construct the set of all variables in the procedure std::set<const IR::Symbol*> all; for(const std::unique_ptr<IR::Symbol> &symbol : mProcedure.symbols()) { all.insert(symbol.get()); } // Construct gen/kill sets for data flow analysis. std::map<const IR::Entry*, std::set<const IR::Symbol*>> gen; std::map<const IR::Entry*, std::set<const IR::Symbol*>> kill; for(const IR::Entry *entry : mProcedure.entries()) { for(const IR::Symbol *symbol : all) { std::set<const IR::Symbol*> &g = gen[entry]; if(entry->uses(symbol)) { // An entry which uses a symbol adds that symbol to the set of live symbols g.insert(symbol); } const IR::Symbol *assign = entry->assign(); if(assign && g.find(assign) == g.end()) { // An entry which assigns to a symbol and does not use it kills that symbol // from the live symbol set kill[entry].insert(assign); } } } // Perform a backwards data flow analysis on the procedure, using the gen and kill sets // constructed above. DataFlow<const IR::Symbol*> dataFlow; mMap = dataFlow.analyze(flowGraph, gen, kill, all, DataFlow<const IR::Symbol*>::Meet::Union, DataFlow<const IR::Symbol*>::Direction::Backward); Util::log("opt.time") << " LiveVariables(" << mProcedure.name() << "): " << timer.stop() << "ms" << std::endl; }
//! ---|> Evaluator void OccOverheadEvaluator::measure(FrameContext & context,Node & node,const Geometry::Rect & /*r*/) { //float currentRenderingTime=0; //int numTests=0; //int numVBO=0; int numPoly=0; Util::Color4f clearColor(0.5f, 0.5f, 0.9f, 1.0f); { // 1. normal render pass // rc.clearScreen(0.5,0.5,0.9); // context.getRenderingContext().finish(); // node.display(rc,renderingFlags); context.getRenderingContext().clearScreen(clearColor); node.display(context,renderingFlags|USE_WORLD_MATRIX); context.getRenderingContext().clearScreen(clearColor); context.getRenderingContext().finish(); context.getStatistics().beginFrame(); node.display(context,renderingFlags|USE_WORLD_MATRIX); context.getRenderingContext().finish(); context.getStatistics().endFrame(); numPoly=static_cast<int>(context.getStatistics().getValueAsDouble(context.getStatistics().getTrianglesCounter())); } // 2. test all group nodes if their bb is visible and collect them std::deque<GroupNode *> visibleGroupNodes; { // collect geometry nodes in frustum const auto groupNodesInVFList = collectNodesInFrustum<GroupNode>(&node,context.getCamera()->getFrustum()); // setup occlusion queries int numQueries=groupNodesInVFList.size(); if (numQueries==0) { values->push_back(nullptr); // TODO!!! return; // TODO?? } auto queries = new Rendering::OcclusionQuery[numQueries]; // test bounding boxes context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, true, Rendering::Comparison::LEQUAL)); int i=0; // start queries Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext()); for(const auto & groupNode : groupNodesInVFList) { queries[i].begin(); // queries[i].fastBoxTest((*it)->getWorldBB()); Rendering::drawAbsBox(context.getRenderingContext(), groupNode->getWorldBB() ); queries[i].end(); ++i; } Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext()); i=0; // get results for(const auto & groupNode : groupNodesInVFList) { Geometry::Box extendedBox=groupNode->getWorldBB(); extendedBox.resizeAbs(context.getCamera()->getNearPlane()); if (queries[i].getResult() > 0 || extendedBox.contains(context.getCamera()->getWorldOrigin()) ) { visibleGroupNodes.push_back(groupNode); } ++i; } context.getRenderingContext().popDepthBuffer(); delete [] queries; } std::deque<GeometryNode *> geoNodesInVisibleGroupNodes; // 3. collect all direct geometry-node children { struct GeoChildrenCollector:public NodeVisitor { GeoChildrenCollector(std::deque<GeometryNode*> & _geoNodes,FrameContext & _context): geoNodes(_geoNodes),firstNode(true),frameContext(_context) {} virtual ~GeoChildrenCollector() {} std::deque<GeometryNode*> & geoNodes; bool firstNode; FrameContext & frameContext; // ---|> NodeVisitor NodeVisitor::status enter(Node * _node) override { // if this is the first call, continue... if(firstNode) { firstNode=false; return CONTINUE_TRAVERSAL; } // else collect the geometry children and break the traversal. GeometryNode * gn=dynamic_cast<GeometryNode *>(_node); if(gn){ if(frameContext.getCamera()->testBoxFrustumIntersection( _node->getWorldBB()) != Geometry::Frustum::intersection_t::OUTSIDE) geoNodes.push_back(gn); } return BREAK_TRAVERSAL; } }; for (auto & visibleGroupNode : visibleGroupNodes) { GeoChildrenCollector vis(geoNodesInVisibleGroupNodes,context); (visibleGroupNode)->traverse(vis); } } // 4. clear screen and measure time drawing children float perfectRenderingTime=0; { context.getRenderingContext().clearScreen(clearColor); context.getRenderingContext().finish(); Util::Timer timer; timer.reset(); for (auto & geoNodesInVisibleGroupNode : geoNodesInVisibleGroupNodes) { context.displayNode((geoNodesInVisibleGroupNode),renderingFlags|USE_WORLD_MATRIX); } context.getRenderingContext().finish(); timer.stop(); perfectRenderingTime=timer.getMilliseconds(); } // // Test-costs: // float result=numTests!=0?(currentRenderingTime-perfectRenderingTime)/numTests:0; // currentRenderingTime-perfRendering: // float result=currentRenderingTime-perfectRenderingTime; float result=numPoly>0?perfectRenderingTime*1000/numPoly:0; // std::cout <<currentRenderingTime<<"-"<<perfectRenderingTime<<"="<<result<<"\t"<<numTests<<"\n"; // std::cout <<numVBO<<":"<<geoNodesInVisibleGroupNodes.size()<<"\n"; // float result=perfectRenderingTime; // values.push_back(currentRenderingTime); // values.push_back(perfectRenderingTime); values->push_back(new Util::_NumberAttribute<float>(result)); // if(mode==SINGLE_VALUE){ // if(result>renderingTime || renderingTime==0) // renderingTime=result; // }else{ // values.push_back(result); // } // renderingTime=0; }
int test_spherical_sampling_serialization() { #ifdef MINSG_EXT_SVS std::cout << "Test serialization of SVS objects ... "; Util::Timer timer; timer.reset(); using namespace MinSG::SVS; MinSG::SceneManagement::SceneManager sceneManager; const uint32_t count = 10; std::array<Util::Reference<MinSG::GeometryNode>, count> nodes; for(uint_fast32_t i = 0; i < count; ++i) { nodes[i] = new MinSG::GeometryNode; sceneManager.registerNode(std::string("Node") + Util::StringUtils::toString(i), nodes[i].get()); } MinSG::VisibilitySubdivision::VisibilityVector vv; for(uint_fast32_t i = 0; i < count; ++i) { vv.setNode(nodes[i].get(), i); } std::vector<SamplePoint> samples; { using namespace Rendering::MeshUtils::PlatonicSolids; Util::Reference<Rendering::Mesh> mesh = createEdgeSubdivisionSphere(createIcosahedron(), 4); auto accessor = Rendering::PositionAttributeAccessor::create(mesh->openVertexData(), Rendering::VertexAttributeIds::POSITION); for(std::size_t i = 0; accessor->checkRange(i); ++i) { samples.emplace_back(accessor->getPosition(i)); } } { std::stringstream stream; stream.precision(std::numeric_limits<long double>::digits10); // Serialize for(const auto & sample : samples) { stream << sample.getPosition() << ' '; sample.getValue().serialize(stream, sceneManager); stream << ' '; } // Unserialize std::vector<SamplePoint> newSamples; for(std::size_t s = 0; s < samples.size(); ++s) { Geometry::Vec3f pos; stream >> pos; SamplePoint sample(pos); sample.setValue(MinSG::VisibilitySubdivision::VisibilityVector::unserialize(stream, sceneManager)); newSamples.push_back(sample); } for(std::size_t s = 0; s < samples.size(); ++s) { const SamplePoint & oldSample = samples[s]; const SamplePoint & newSample = newSamples[s]; if(oldSample.getPosition().distance(newSample.getPosition()) > std::numeric_limits<float>::epsilon()) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } const auto & oldVV = oldSample.getValue(); const auto & newVV = newSample.getValue(); for(uint_fast32_t n = 0; n < count; ++n) { if(oldVV.getBenefits(nodes[n].get()) != newVV.getBenefits(nodes[n].get())) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } } } } VisibilitySphere visibilitySphere(Geometry::Sphere_f(Geometry::Vec3f(1.0f, 2.0f, 3.0f), 17.0f), samples); { std::stringstream stream; stream.precision(std::numeric_limits<long double>::digits10); // Serialize stream << visibilitySphere.getSphere() << ' ' << samples.size(); for(const auto & sample : samples) { stream << ' ' << sample.getPosition() << ' '; sample.getValue().serialize(stream, sceneManager); stream << ' '; } // Unserialize Geometry::Sphere_f sphere; stream >> sphere; std::size_t sampleCount; stream >> sampleCount; std::vector<SamplePoint> newSamples; for(std::size_t s = 0; s < sampleCount; ++s) { Geometry::Vec3f pos; stream >> pos; SamplePoint sample(pos); sample.setValue(MinSG::VisibilitySubdivision::VisibilityVector::unserialize(stream, sceneManager)); newSamples.push_back(sample); } VisibilitySphere newVisibilitySphere(sphere, newSamples); if(!(visibilitySphere.getSphere() == newVisibilitySphere.getSphere())) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } for(std::size_t s = 0; s < samples.size(); ++s) { const SamplePoint & oldSample = visibilitySphere.getSamples()[s]; const SamplePoint & newSample = newVisibilitySphere.getSamples()[s]; if(oldSample.getPosition().distance(newSample.getPosition()) > std::numeric_limits<float>::epsilon()) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } const auto & oldVV = oldSample.getValue(); const auto & newVV = newSample.getValue(); for(uint_fast32_t n = 0; n < count; ++n) { if(oldVV.getBenefits(nodes[n].get()) != newVV.getBenefits(nodes[n].get())) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } } } } timer.stop(); std::cout << "done (duration: " << timer.getSeconds() << " s).\n"; #endif /* MINSG_EXT_SVS */ return EXIT_SUCCESS; }
int test_spherical_sampling() { #ifdef MINSG_EXT_SVS std::cout << "Test SVS ... "; Util::Timer timer; timer.reset(); MinSG::SceneManagement::SceneManager sceneManager; MinSG::FrameContext frameContext; Rendering::VertexDescription vertexDesc; vertexDesc.appendPosition3D(); Util::Reference<Rendering::Mesh> boxMesh = Rendering::MeshUtils::MeshBuilder::createBox(vertexDesc, Geometry::Box(Geometry::Vec3f(0.5f, 0.5f, 0.5f), 1)); /* * Create a 1D array of n unit-size boxes in the x axis * * / * ..L2 * / / * ......L1 / * / / / * ...L0.... / / * / / / / / * ------------------------- ... ----- * | 0 | 1 | 2 | 3 | 4 | 5 | | n | * | | | | | | | | | * ------------------------- ... ----- * ^ ^ ^ * | | | * x=0 x=4 x=n * * The first three boxes are put into the first list node L0. * L0 together with the fourth box are put into the second list node L1. */ const uint32_t count = 512; std::vector<Util::Reference<MinSG::ListNode>> listNodes; std::vector<Util::Reference<MinSG::GeometryNode>> boxNodes; for(uint_fast32_t x = 0; x < count; ++x) { MinSG::GeometryNode * geoNode = new MinSG::GeometryNode(boxMesh); geoNode->moveLocal(Geometry::Vec3f(x, 0, 0)); sceneManager.registerNode(std::string("Node") + Util::StringUtils::toString(x), geoNode); boxNodes.push_back(geoNode); if(x != 1 && x != 2) { listNodes.push_back(new MinSG::ListNode); } if(x < 3) { listNodes.front()->addChild(geoNode); } else { listNodes[x - 2]->addChild(listNodes[x - 3].get()); listNodes[x - 2]->addChild(geoNode); } } // Debug output of created scene graph //MinSG::GraphVizOutput::treeToFile(listNodes.back().get(), &sceneManager, Util::FileName("output.dot")); // Perform the sampling std::vector<Geometry::Vec3f> positions; positions.emplace_back(-1, 0, 0); // left positions.emplace_back(1, 0, 0); // right positions.emplace_back(0, 1, 0); // top positions.emplace_back(0, 0, 1); // back // The resolution has to be at least the number of boxes. Otherwise, boxes will be missed during visibility testing. MinSG::SVS::PreprocessingContext preprocessingContext(sceneManager, frameContext, listNodes.back().get(), positions, count, false, false); while(!preprocessingContext.isFinished()) { preprocessingContext.preprocessSingleNode(); } // Validate the results for(uint_fast32_t listIndex = 0; listIndex < count - 2; ++listIndex) { MinSG::ListNode * listNode = listNodes[listIndex].get(); const MinSG::SVS::VisibilitySphere & visibilitySphere = MinSG::SVS::retrieveVisibilitySphere(listNode); { // Because the geometry is built of axis-aligned bounding boxes only, the sphere has to contain the group's bounding box. assert(visibilitySphere.getSphere().distance(listNode->getBB().getMin()) < 1.0e-9); assert(visibilitySphere.getSphere().distance(listNode->getBB().getMax()) < 1.0e-9); } { // left => only first box must be visible const auto vv = visibilitySphere.queryValue(positions[0], MinSG::SVS::INTERPOLATION_NEAREST); assert(vv.getBenefits(boxNodes.front().get()) > 0); for(uint_fast32_t boxIndex = 1; boxIndex < count; ++boxIndex) { MinSG::GeometryNode * geoNode = boxNodes[boxIndex].get(); assert(vv.getBenefits(geoNode) == 0); } } { // right => only last box inside the subtree must be visible const auto vv = visibilitySphere.queryValue(positions[1], MinSG::SVS::INTERPOLATION_NEAREST); const uint32_t lastBoxIndex = listIndex + 2; assert(vv.getBenefits(boxNodes[lastBoxIndex].get()) > 0); for(uint_fast32_t boxIndex = 0; boxIndex < count; ++boxIndex) { if(boxIndex != lastBoxIndex) { MinSG::GeometryNode * geoNode = boxNodes[boxIndex].get(); assert(vv.getBenefits(geoNode) == 0); } } } // top, back => all boxes in the subtree must be visible for(uint_fast32_t posIndex = 2; posIndex <= 3; ++posIndex) { const auto vv = visibilitySphere.queryValue(positions[posIndex], MinSG::SVS::INTERPOLATION_NEAREST); const auto geoNodes = MinSG::collectNodes<MinSG::GeometryNode>(listNode); for(const auto & geoNode : geoNodes) { assert(vv.getBenefits(geoNode) > 0); } } } boxNodes.clear(); MinSG::destroy(listNodes.back().get()); listNodes.clear(); timer.stop(); std::cout << "done (duration: " << timer.getSeconds() << " s).\n"; #endif /* MINSG_EXT_SVS */ return EXIT_SUCCESS; }
int test_OutOfCore() { #ifdef MINSG_EXT_OUTOFCORE const bool verbose = true; // Tests for MinSG::OutOfCore::CacheObjectPriority if(sizeof(MinSG::OutOfCore::CacheObjectPriority) != 8) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(1, 2, 3) == MinSG::OutOfCore::CacheObjectPriority(1, 2, 3))) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(1, 100, 100) < MinSG::OutOfCore::CacheObjectPriority(2, 0, 0))) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(2, 1, 100) < MinSG::OutOfCore::CacheObjectPriority(2, 2, 0))) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(2, 2, 1) < MinSG::OutOfCore::CacheObjectPriority(2, 2, 2))) { return EXIT_FAILURE; } std::default_random_engine engine; std::uniform_int_distribution<std::size_t> vertexCountDist(10, 1000); const uint32_t numMeshes = 30000; const Util::TemporaryDirectory tempDir("MinSGTest_OutOfCore"); // Create empty meshes and save them into a subdirectory. { Rendering::VertexDescription vertexDesc; vertexDesc.appendPosition3D(); for(uint_fast32_t i = 0; i < numMeshes; ++i) { Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, vertexCountDist(engine), 64); Rendering::MeshVertexData & vertexData = mesh->openVertexData(); std::fill_n(vertexData.data(), vertexData.dataSize(), 0); vertexData.markAsChanged(); Rendering::MeshIndexData & indexData = mesh->openIndexData(); std::fill_n(indexData.data(), indexData.getIndexCount(), 0); indexData.markAsChanged(); const std::string numberString = Util::StringUtils::toString<uint32_t>(i); Rendering::Serialization::saveMesh(mesh.get(), Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf")); } } // Set up the OutOfCore system. MinSG::FrameContext frameContext; MinSG::OutOfCore::setUp(frameContext); MinSG::OutOfCore::CacheManager & manager = MinSG::OutOfCore::getCacheManager(); manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::FILE_SYSTEM, 0); manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::FILES, 512 * kibibyte); manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::MAIN_MEMORY, 256 * kibibyte); Util::Timer addTimer; addTimer.reset(); std::cout << "Adding meshes ..." << std::flush; // Add the meshes to the OutOfCore system. std::vector<Util::Reference<Rendering::Mesh> > meshes; meshes.reserve(numMeshes); static const Geometry::Box boundingBox(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); for(uint_fast32_t i = 0; i < numMeshes; ++i) { const std::string numberString = Util::StringUtils::toString<uint32_t>(i); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); } manager.trigger(); addTimer.stop(); std::cout << " done (" << addTimer.getSeconds() << " s)" << std::endl; Util::Timer displayTimer; Util::Timer assureLocalTimer; Util::Timer overallTimer; overallTimer.reset(); uint32_t frame = 0; { // Simulate frames to get the OutOfCore system working. std::uniform_int_distribution<std::size_t> indexDist(0, meshes.size() - 1); for(; frame < 10; ++frame) { std::cout << "Executing frame " << frame << " ..." << std::flush; frameContext.beginFrame(); displayTimer.reset(); // Simulate display of meshes to change the priorities of the system. for(uint32_t i = 0; i < meshes.size() / 2; ++i) { const uint32_t meshIndex = indexDist(engine); Rendering::Mesh * mesh = meshes[meshIndex].get(); manager.meshDisplay(mesh); } manager.trigger(); displayTimer.stop(); assureLocalTimer.reset(); for(uint32_t i = 0; i < 10; ++i) { const uint32_t meshIndex = indexDist(engine); Rendering::Mesh * mesh = meshes[meshIndex].get(); const Rendering::MeshVertexData & vd = mesh->openVertexData(); const Rendering::MeshIndexData & id = mesh->openIndexData(); if (!vd.hasLocalData() || !id.hasLocalData()) { std::cout << "Error: Mesh has no local data." << std::endl; return EXIT_FAILURE; } } assureLocalTimer.stop(); frameContext.endFrame(); std::cout << " done (display: " << displayTimer.getSeconds() << " s, assureLocal: " << assureLocalTimer.getSeconds() << " s)" << std::endl; if(verbose) { outputCacheLevelInformation(); } } } for(uint32_t round = 0; round < 10; ++round) { Util::Timer addAgainTimer; addAgainTimer.reset(); std::cout << "Adding additional meshes ..." << std::flush; // Simulate loading a second scene by adding meshes again. meshes.reserve(meshes.size() + 3 * numMeshes); for(uint_fast32_t i = 0; i < numMeshes; ++i) { const std::string numberString = Util::StringUtils::toString<uint32_t>(i); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); } manager.trigger(); addAgainTimer.stop(); std::cout << " done (" << addAgainTimer.getSeconds() << " s)" << std::endl; // Simulate frames to get the OutOfCore system working. std::normal_distribution<double> indexDist(meshes.size() / 2, std::sqrt(meshes.size() / 2)); const auto untilFrame = frame + 5; for(; frame < untilFrame; ++frame) { std::cout << "Executing frame " << frame << " ..." << std::flush; frameContext.beginFrame(); displayTimer.reset(); // Simulate display of meshes to change the priorities of the system. for(uint32_t i = 0; i < meshes.size() / 10; ++i) { const std::size_t meshIndex = std::max(static_cast<std::size_t>(0), std::min(static_cast<std::size_t>(indexDist(engine)), meshes.size() - 1)); Rendering::Mesh * mesh = meshes[meshIndex].get(); manager.meshDisplay(mesh); } manager.trigger(); displayTimer.stop(); frameContext.endFrame(); std::cout << " done (display: " << displayTimer.getSeconds() << " s)" << std::endl; if(verbose) { outputCacheLevelInformation(); } } } overallTimer.stop(); std::cout << "Overall duration: " << overallTimer.getSeconds() << " s" << std::endl; MinSG::OutOfCore::shutDown(); return EXIT_SUCCESS; #else /* MINSG_EXT_OUTOFCORE */ return EXIT_FAILURE; #endif /* MINSG_EXT_OUTOFCORE */ }
/*! * \brief Optimize a program * \param program Program to optimize */ void Optimizer::optimize(IR::Program &program) { std::vector<Transform::Transform*> startingTransforms; std::map<Transform::Transform*, std::vector<Transform::Transform*>> transformMap; // Build the list of all transforms startingTransforms.push_back(Transform::CopyProp::instance()); startingTransforms.push_back(Transform::ConstantProp::instance()); startingTransforms.push_back(Transform::DeadCodeElimination::instance()); startingTransforms.push_back(Transform::ThreadJumps::instance()); startingTransforms.push_back(Transform::LoopInvariantCodeMotion::instance()); startingTransforms.push_back(Transform::CommonSubexpressionElimination::instance()); // Transforms to run after CopyProp transformMap[Transform::CopyProp::instance()].push_back(Transform::DeadCodeElimination::instance()); // Transforms to run after Constant Prop transformMap[Transform::ConstantProp::instance()].push_back(Transform::DeadCodeElimination::instance()); // Transforms to run after DeadCodeElimination transformMap[Transform::DeadCodeElimination::instance()].push_back(Transform::ConstantProp::instance()); transformMap[Transform::DeadCodeElimination::instance()].push_back(Transform::CopyProp::instance()); // Transforms to run after CommonSubexpressionElimination transformMap[Transform::CommonSubexpressionElimination::instance()].push_back(Transform::CopyProp::instance()); // Optimize each procedure in turn for(std::unique_ptr<IR::Procedure> &procedure : program.procedures()) { Analysis::Analysis analysis(*procedure); // Queue of transformations to run Util::UniqueQueue<Transform::Transform*> transforms; // Start by running each optimization pass once for(Transform::Transform *transform : startingTransforms) { transforms.push(transform); } Util::log("opt") << "Optimizations (" << procedure->name() << "):" << std::endl; // Run optimization passes until there are none left while(!transforms.empty()) { Transform::Transform *transform = transforms.front(); transforms.pop(); // Run the transform Util::Timer timer; timer.start(); bool changed = transform->transform(*procedure, analysis); Util::log("opt.time") << transform->name() << ": " << timer.stop() << "ms" << std::endl; if(changed) { procedure->print(Util::log("opt.ir")); Util::log("opt.ir") << std::endl; // If the transform changed the IR, add its follow-up transformations to the queue std::vector<Transform::Transform*> &newTransforms = transformMap[transform]; for(Transform::Transform *newTransform : newTransforms) { transforms.push(newTransform); } } } Util::log("opt") << std::endl; } }