void BackgroundLoader::FinishResources(int maxMs) { if (IsStarted()) { HiresTimer timer; backgroundLoadMutex_.Acquire(); for (auto i = backgroundLoadQueue_.begin(); i != backgroundLoadQueue_.end();) { Resource* resource = i->second.resource_; unsigned numDeps = i->second.dependencies_.size(); AsyncLoadState state = resource->GetAsyncLoadState(); if (numDeps > 0 || state == ASYNC_QUEUED || state == ASYNC_LOADING) ++i; else { // Finishing a resource may need it to wait for other resources to load, in which case we can not // hold on to the mutex backgroundLoadMutex_.Release(); FinishBackgroundLoading(i->second); backgroundLoadMutex_.Acquire(); i = backgroundLoadQueue_.erase(i); } // Break when the time limit passed so that we keep sufficient FPS if (timer.GetUSec(false) >= maxMs * 1000LL) break; } backgroundLoadMutex_.Release(); } }
//============================================================================= //============================================================================= void StaticModelPoolMgr::CreateBVH() { // default settings Platform platform; BVH::BuildParams params; BVH::Stats bvhStats; params.stats = &bvhStats; // disable print in NVraytrav params.enablePrints = false; // create bvh HiresTimer htimer; m_pNvScene->CreateBVH( &platform, ¶ms ); long long elapsed = htimer.GetUSec( true ); // stats params.enablePrints = true; if ( params.enablePrints ) { const BVHNode *root = m_pNvScene->GetBVHRoot(); SDL_Log("BVH build time=%I64d msec\n", elapsed/1000); SDL_Log("BVH builder: %d tris, %d vertices\n", m_pNvScene->getNumTriangles(), m_pNvScene->getNumVertices()); SDL_Log("BVH: Scene bounds: (%.1f,%.1f,%.1f) - (%.1f,%.1f,%.1f)\n", root->m_bounds.min().x, root->m_bounds.min().y, root->m_bounds.min().z, root->m_bounds.max().x, root->m_bounds.max().y, root->m_bounds.max().z); SDL_Log("BVH: SAHCost = %.2f\n", params.stats->SAHCost ); SDL_Log("BVH: branchingFactor = %d\n", params.stats->branchingFactor ); SDL_Log("BVH: numLeafNodes = %d\n", params.stats->numLeafNodes ); SDL_Log("BVH: numInnerNodes = %d\n", params.stats->numInnerNodes ); SDL_Log("BVH: numTris = %d\n", params.stats->numTris ); SDL_Log("BVH: numChildNodes = %d\n", params.stats->numChildNodes ); } }
void Scene::UpdateAsyncLoading() { PROFILE(UpdateAsyncLoading); // If resources left to load, do not load nodes yet if (asyncProgress_.loadedResources_ < asyncProgress_.totalResources_) return; HiresTimer asyncLoadTimer; for (;;) { if (asyncProgress_.loadedNodes_ >= asyncProgress_.totalNodes_) { FinishAsyncLoading(); return; } // Read one child node with its full sub-hierarchy either from binary or XML /// \todo Works poorly in scenes where one root-level child node contains all content if (!asyncProgress_.xmlFile_) { unsigned nodeID = asyncProgress_.file_->ReadUInt(); Node* newNode = CreateChild(nodeID, nodeID < FIRST_LOCAL_ID ? REPLICATED : LOCAL); resolver_.AddNode(nodeID, newNode); newNode->Load(*asyncProgress_.file_, resolver_); } else { unsigned nodeID = asyncProgress_.xmlElement_.GetInt("id"); Node* newNode = CreateChild(nodeID, nodeID < FIRST_LOCAL_ID ? REPLICATED : LOCAL); resolver_.AddNode(nodeID, newNode); newNode->LoadXML(asyncProgress_.xmlElement_, resolver_); asyncProgress_.xmlElement_ = asyncProgress_.xmlElement_.GetNext("node"); } ++asyncProgress_.loadedNodes_; // Break if time limit exceeded, so that we keep sufficient FPS if (asyncLoadTimer.GetUSec(false) >= asyncLoadingMs_ * 1000) break; } using namespace AsyncLoadProgress; VariantMap& eventData = GetEventDataMap(); eventData[P_SCENE] = this; eventData[P_PROGRESS] = GetAsyncProgress(); eventData[P_LOADEDNODES] = asyncProgress_.loadedNodes_; eventData[P_TOTALNODES] = asyncProgress_.totalNodes_; eventData[P_LOADEDRESOURCES] = asyncProgress_.loadedResources_; eventData[P_TOTALRESOURCES] = asyncProgress_.totalResources_; SendEvent(E_ASYNCLOADPROGRESS, eventData); }
void BackgroundLoader::WaitForResource(StringHash type, StringHash nameHash) { backgroundLoadMutex_.Acquire(); // Check if the resource in question is being background loaded ea::pair<StringHash, StringHash> key = ea::make_pair(type, nameHash); auto i = backgroundLoadQueue_.find( key); if (i != backgroundLoadQueue_.end()) { backgroundLoadMutex_.Release(); { Resource* resource = i->second.resource_; HiresTimer waitTimer; bool didWait = false; for (;;) { unsigned numDeps = i->second.dependencies_.size(); AsyncLoadState state = resource->GetAsyncLoadState(); if (numDeps > 0 || state == ASYNC_QUEUED || state == ASYNC_LOADING) { didWait = true; Time::Sleep(1); } else break; } if (didWait) URHO3D_LOGDEBUG("Waited " + ea::to_string(waitTimer.GetUSec(false) / 1000) + " ms for background loaded resource " + resource->GetName()); } // This may take a long time and may potentially wait on other resources, so it is important we do not hold the mutex during this FinishBackgroundLoading(i->second); backgroundLoadMutex_.Acquire(); backgroundLoadQueue_.erase(i); backgroundLoadMutex_.Release(); } else backgroundLoadMutex_.Release(); }
void WorkQueue::HandleBeginFrame(StringHash eventType, VariantMap& eventData) { // If no worker threads, complete low-priority work here if (threads_.Empty() && !queue_.Empty()) { URHO3D_PROFILE(CompleteWorkNonthreaded); HiresTimer timer; while (!queue_.Empty() && timer.GetUSec(false) < maxNonThreadedWorkMs_ * 1000) { WorkItem* item = queue_.Front(); queue_.PopFront(); item->workFunction_(item, 0); item->completed_ = true; } } // Complete and signal items down to the lowest priority PurgeCompleted(0); PurgePool(); }
int main() { #ifdef _MSC_VER _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif printf("Size of String: %d\n", sizeof(String)); printf("Size of Vector: %d\n", sizeof(Vector<int>)); printf("Size of List: %d\n", sizeof(List<int>)); printf("Size of HashMap: %d\n", sizeof(HashMap<int, int>)); printf("Size of RefCounted: %d\n", sizeof(RefCounted)); { printf("\nTesting AutoPtr assignment\n"); AutoPtr<Test> ptr1(new Test); AutoPtr<Test> ptr2; ptr2 = ptr1; } { printf("\nTesting AutoPtr copy construction\n"); AutoPtr<Test> ptr1(new Test); AutoPtr<Test> ptr2(ptr1); } { printf("\nTesting AutoPtr detaching\n"); AutoPtr<Test> ptr1(new Test); // We would now have a memory leak if we don't manually delete the object Test* object = ptr1.Detach(); delete object; } { printf("\nTesting AutoPtr inside a vector\n"); Vector<AutoPtr<Test> > vec; printf("Filling vector\n"); for (size_t i = 0; i < 4; ++i) vec.Push(new Test()); printf("Clearing vector\n"); vec.Clear(); } { printf("\nTesting SharedPtr\n"); SharedPtr<TestRefCounted> ptr1(new TestRefCounted); SharedPtr<TestRefCounted> ptr2(ptr1); printf("Number of refs: %d\n", ptr1.Refs()); } { printf("\nTesting WeakPtr\n"); TestRefCounted* object = new TestRefCounted; WeakPtr<TestRefCounted> ptr1(object); WeakPtr<TestRefCounted> ptr2(ptr1); printf("Number of weak refs: %d expired: %d\n", ptr1.WeakRefs(), ptr1.IsExpired()); ptr2.Reset(); delete object; printf("Number of weak refs: %d expired: %d\n", ptr1.WeakRefs(), ptr1.IsExpired()); } { printf("\nTesting Vector\n"); HiresTimer t; Vector<int> vec; SetRandomSeed(0); for (size_t i = 0; i < NUM_ITEMS; ++i) vec.Push(Rand()); int sum = 0; int count = 0; for (auto it = vec.Begin(); it != vec.End(); ++it) { sum += *it; ++count; } int usec = (int)t.ElapsedUSec(); printf("Size: %d capacity: %d\n", vec.Size(), vec.Capacity()); printf("Counted vector items %d, sum: %d\n", count, sum); printf("Processing took %d usec\n", usec); } { printf("\nTesting List\n"); HiresTimer t; List<int> list; SetRandomSeed(0); for (size_t i = 0; i < NUM_ITEMS; ++i) list.Push(Rand()); int sum = 0; int count = 0; for (auto it = list.Begin(); it != list.End(); ++it) { sum += *it; ++count; } int usec = (int)t.ElapsedUSec(); printf("Size: %d\n", list.Size()); printf("Counted list items %d, sum: %d\n", count, sum); printf("Processing took %d usec\n", usec); printf("\nTesting List insertion\n"); List<int> list2; List<int> list3; for (int i = 0; i < 10; ++i) list3.Push(i); list2.Insert(list2.End(), list3); for (auto it = list2.Begin(); it != list2.End(); ++it) printf("%d ", *it); printf("\n"); } { printf("\nTesting String\n"); HiresTimer t; String test; for (size_t i = 0; i < NUM_ITEMS/4; ++i) test += "Test"; String test2; test2.AppendWithFormat("Size: %d capacity: %d\n", test.Length(), test.Capacity()); printf(test2.CString()); test2 = test2.ToUpper(); printf(test2.CString()); test2.Replace("SIZE:", "LENGTH:"); printf(test2.CString()); int usec = (int)t.ElapsedUSec(); printf("Processing took %d usec\n", usec); } { printf("\nTesting HashSet\n"); HiresTimer t; size_t found = 0; unsigned sum = 0; HashSet<int> testHashSet; srand(0); found = 0; sum = 0; printf("Insert, search and iteration, %d keys\n", NUM_ITEMS); for (size_t i = 0; i < NUM_ITEMS; ++i) { int number = (rand() & 32767); testHashSet.Insert(number); } for (int i = 0; i < 32768; ++i) { if (testHashSet.Find(i) != testHashSet.End()) ++found; } for (auto it = testHashSet.Begin(); it != testHashSet.End(); ++it) sum += *it; int usec = (int)t.ElapsedUSec(); printf("Set size and sum: %d %d\n", testHashSet.Size(), sum); printf("Processing took %d usec\n", usec); } { printf("\nTesting HashMap\n"); HashMap<int, int> testHashMap; for (int i = 0; i < 10; ++i) testHashMap.Insert(MakePair(i, rand() & 32767)); printf("Keys: "); Vector<int> keys = testHashMap.Keys(); for (size_t i = 0; i < keys.Size(); ++i) printf("%d ", keys[i]); printf("\n"); printf("Values: "); Vector<int> values = testHashMap.Values(); for (size_t i = 0; i < values.Size(); ++i) printf("%d ", values[i]); printf("\n"); } return 0; }