Ejemplo n.º 1
0
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, &params );
    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 );
    }
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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();
}
Ejemplo n.º 5
0
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();
}