コード例 #1
0
ファイル: treeEqualizer.cpp プロジェクト: bohara/Equalizer
void TreeEqualizer::_notifyLoadData( Node* node, Channel* channel,
                                     const uint32_t nStatistics,
                                     const Statistic* statistics )
{
    if( !node )
        return;

    _notifyLoadData( node->left, channel, nStatistics, statistics );
    _notifyLoadData( node->right, channel, nStatistics, statistics );

    if( !node->compound || node->compound->getChannel() != channel )
        return;

    // gather relevant load data
    const uint32_t taskID = node->compound->getTaskID();
    int64_t startTime = std::numeric_limits< int64_t >::max();
    int64_t endTime   = 0;
    bool    loadSet   = false;
    int64_t timeTransmit = 0;
    for( uint32_t i = 0; i < nStatistics && !loadSet; ++i )
    {
        const Statistic& stat = statistics[ i ];
        if( stat.task != taskID ) // from different compound
            continue;

        switch( stat.type )
        {
        case Statistic::CHANNEL_CLEAR:
        case Statistic::CHANNEL_DRAW:
        case Statistic::CHANNEL_READBACK:
            startTime = LB_MIN( startTime, stat.startTime );
            endTime   = LB_MAX( endTime, stat.endTime );
            break;

        case Statistic::CHANNEL_ASYNC_READBACK:
        case Statistic::CHANNEL_FRAME_TRANSMIT:
            timeTransmit += stat.endTime - stat.startTime;
            break;

        // assemble blocks on input frames, stop using subsequent data
        case Statistic::CHANNEL_ASSEMBLE:
            loadSet = true;
            break;

        default:
            break;
        }
    }

    if( startTime == std::numeric_limits< int64_t >::max( ))
        return;

    node->time = endTime - startTime;
    node->time = LB_MAX( node->time, 1 );
    node->time = LB_MAX( node->time, timeTransmit );
}
コード例 #2
0
ファイル: config.cpp プロジェクト: steiner-/Equalizer
void Config::_adjustResistance( const int delta )
{
    View* view = _getCurrentView();
    if( !view )
        return;

    eq::Vector2i size = view->getEqualizer().getResistance2i();
    size += delta;
    size.x() = LB_MAX( size.x(), 0 );
    size.y() = LB_MAX( size.y(), 0 );
    std::ostringstream stream;
    stream << "Set load equalizer resistance to " << size;
    _setMessage( stream.str( ));
    view->getEqualizer().setResistance( size );
}
コード例 #3
0
void FramerateEqualizer::_init()
{
    const Compound* compound = getCompound();

    if( _nSamples > 0 || !compound )
        return;

    _nSamples = 1;

    // Subscribe to child channel load events
    const Compounds& children = compound->getChildren();

    LBASSERT( _loadListeners.empty( ));
    _loadListeners.resize( children.size( ));

    for( size_t i = 0; i < children.size(); ++i )
    {
        Compound*      child        = children[i];
        const uint32_t period       = child->getInheritPeriod();
        LoadListener&  loadListener = _loadListeners[i];

        loadListener.parent = this;
        loadListener.period = period;

        LoadSubscriber subscriber( &loadListener );
        child->accept( subscriber );

        _nSamples = LB_MAX( _nSamples, period );
    }

    _nSamples = LB_MIN( _nSamples, 100 );
}
コード例 #4
0
ファイル: channel.cpp プロジェクト: BillTheBest/Equalizer
void Channel::frameViewFinish( const eq::uint128_t& frameID )
{
    if( stopRendering( ))
        return;

    applyBuffer();

    const FrameData& frameData = _getFrameData();
    Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];

    if( accum.buffer )
    {
        const eq::PixelViewport& pvp = getPixelViewport();
        const bool isResized = accum.buffer->resize( pvp );

        if( isResized )
        {
            const View* view = static_cast< const View* >( getView( ));
            accum.buffer->clear();
            accum.step = view->getIdleSteps();
            accum.stepsDone = 0;
        }
        else if( frameData.isIdle( ))
        {
            setupAssemblyState();

            if( !_isDone() && accum.transfer )
                accum.buffer->accum();
            accum.buffer->display();

            resetAssemblyState();
        }
    }

    applyViewport();
    _drawOverlay();
    _drawHelp();

    if( frameData.useStatistics())
        drawStatistics();

    int32_t steps = 0;
    if( frameData.isIdle( ))
    {
        for( size_t i = 0; i < eq::NUM_EYES; ++i )
            steps = LB_MAX( steps, _accum[i].step );
    }
    else
    {
        const View* view = static_cast< const View* >( getView( ));
        steps = view ? view->getIdleSteps() : 0;
    }

    // if _jitterStep == 0 and no user redraw event happened, the app will exit
    // FSAA idle mode and block on the next redraw event.
    eq::Config* config = getConfig();
    config->sendEvent( IDLE_AA_LEFT ) << steps;

    eq::Channel::frameViewFinish( frameID );
}
コード例 #5
0
ファイル: rawVolModel.cpp プロジェクト: Eyescale/Equalizer
/** Volume always represented as cube [-1,-1,-1]..[1,1,1], so if the model
    is not cube it's proportions should be modified. This function makes
    maximum proportion equal to 1.0 to prevent unnecessary rescaling.
*/
static void normalizeScaling(const uint32_t w, const uint32_t h,
                             const uint32_t d, VolumeScaling& scaling)
{
    // Correct proportions according to real size of volume
    float maxS = float(LB_MAX(w, LB_MAX(h, d)));

    scaling.W *= w / maxS;
    scaling.H *= h / maxS;
    scaling.D *= d / maxS;

    // Make maximum proportion equal to 1.0
    maxS = LB_MAX(scaling.W, LB_MAX(scaling.H, scaling.D));

    scaling.W /= maxS;
    scaling.H /= maxS;
    scaling.D /= maxS;
}
コード例 #6
0
ファイル: channel.cpp プロジェクト: aoighost/Equalizer
void Channel::_updateNearFar( const mesh::BoundingSphere& boundingSphere )
{
    // compute dynamic near/far plane of whole model
    const FrameData& frameData = _getFrameData();

    const eq::Matrix4f& rotation     = frameData.getCameraRotation();
    const eq::Matrix4f headTransform = getHeadTransform() * rotation;

    eq::Matrix4f modelInv;
    compute_inverse( headTransform, modelInv );

    const eq::Vector3f zero  = modelInv * eq::Vector3f::ZERO;
    eq::Vector3f       front = modelInv * eq::Vector3f( 0.0f, 0.0f, -1.0f );

    front -= zero;
    front.normalize();
    front *= boundingSphere.w();

    const eq::Vector3f center =  
        frameData.getCameraPosition().get_sub_vector< 3 >() -
        boundingSphere.get_sub_vector< 3 >();
    const eq::Vector3f nearPoint  = headTransform * ( center - front );
    const eq::Vector3f farPoint   = headTransform * ( center + front );

    if( useOrtho( ))
    {
        LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) > 
                      std::numeric_limits< float >::epsilon(),
                      nearPoint << " == " << farPoint );
        setNearFar( -nearPoint.z(), -farPoint.z() );
    }
    else
    {
        // estimate minimal value of near plane based on frustum size
        const eq::Frustumf& frustum = getFrustum();
        const float width  = fabs( frustum.right() - frustum.left() );
        const float height = fabs( frustum.top() - frustum.bottom() );
        const float size   = LB_MIN( width, height );
        const float minNear = frustum.near_plane() / size * .001f;

        const float zNear = LB_MAX( minNear, -nearPoint.z() );
        const float zFar  = LB_MAX( zNear * 2.f, -farPoint.z() );

        setNearFar( zNear, zFar );
    }
}
コード例 #7
0
ファイル: frameData.cpp プロジェクト: hypronet/Equalizer
void FrameData::adjustQuality( const float delta )
{
    _quality += delta;
    _quality = LB_MAX( _quality, 0.1f );
    _quality = LB_MIN( _quality, 1.0f );
    setDirty( DIRTY_FLAGS );
    LBINFO << "Set non-idle image quality to " << _quality << std::endl;
}
コード例 #8
0
void FramerateEqualizer::LoadListener::notifyLoadData(
    Channel* channel, const uint32_t frameNumber, const Statistics& statistics,
    const Viewport& region  )
{
    // gather required load data
    int64_t startTime = std::numeric_limits< int64_t >::max();
    int64_t endTime   = 0;
    for( size_t i = 0; i < statistics.size(); ++i )
    {
        const eq::Statistic& data = statistics[i];
        switch( data.type )
        {
        case eq::Statistic::CHANNEL_CLEAR:
        case eq::Statistic::CHANNEL_DRAW:
        case eq::Statistic::CHANNEL_ASSEMBLE:
        case eq::Statistic::CHANNEL_READBACK:
            startTime = LB_MIN( startTime, data.startTime );
            endTime   = LB_MAX( endTime, data.endTime );
            break;

        default:
            break;
        }
    }

    if( startTime == std::numeric_limits< int64_t >::max( ))
        return;

    if( startTime == endTime ) // very fast draws might report 0 times
        ++endTime;

    for( std::deque< FrameTime >::iterator i = parent->_times.begin();
            i != parent->_times.end(); ++i )
    {
        FrameTime& frameTime = *i;
        if( frameTime.first != frameNumber )
            continue;

        const float time = static_cast< float >( endTime - startTime ) / period;
        frameTime.second = LB_MAX( frameTime.second, time );
        LBLOG( LOG_LB2 ) << "Frame " << frameNumber << " channel "
                         << channel->getName() << " time " << time
                         << " period " << period << std::endl;
    }
}
コード例 #9
0
ファイル: channel.cpp プロジェクト: aoighost/Equalizer
void Channel::frameAssemble( const eq::uint128_t& frameID )
{
    if( stopRendering( ))
        return;

    if( _isDone( ))
        return;

    Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];

    if( getPixelViewport() != _currentPVP )
    {
        accum.transfer = true;

        if( accum.buffer && !accum.buffer->usesFBO( ))
        {
            LBWARN << "Current viewport different from view viewport, "
                   << "idle anti-aliasing not implemented." << std::endl;
            accum.step = 0;
        }

        eq::Channel::frameAssemble( frameID );
        return;
    }
    // else
    
    accum.transfer = true;
    const eq::Frames& frames = getInputFrames();

    for( eq::Frames::const_iterator i = frames.begin(); i != frames.end(); ++i )
    {
        eq::Frame* frame = *i;
        const eq::SubPixel& curSubPixel = frame->getSubPixel();

        if( curSubPixel != eq::SubPixel::ALL )
            accum.transfer = false;

        accum.stepsDone = LB_MAX( accum.stepsDone, 
                                  frame->getSubPixel().size*frame->getPeriod( ));
    }

    applyBuffer();
    applyViewport();
    setupAssemblyState();

    try
    {
        eq::Compositor::assembleFrames( getInputFrames(), this, accum.buffer );
    }
    catch( const co::Exception& e )
    {
        LBWARN << e.what() << std::endl;
    }

    resetAssemblyState();
}
コード例 #10
0
void Channel::frameAssemble( const eq::uint128_t& frameID,
                             const eq::Frames& frames )
{
    if( stopRendering( ))
        return;

    if( _isDone( ))
        return;

    Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];

    if( getPixelViewport() != _currentPVP )
    {
        accum.transfer = true;

        if( accum.buffer && !accum.buffer->usesFBO( ))
        {
            LBWARN << "Current viewport different from view viewport, "
                   << "idle anti-aliasing not implemented." << std::endl;
            accum.step = 0;
        }

        eq::Channel::frameAssemble( frameID, frames );
        return;
    }
    // else

    accum.transfer = true;
    for( eq::Frame* frame : frames )
    {
        const eq::SubPixel& subPixel =
            frame->getFrameData()->getContext().subPixel;

        if( subPixel != eq::SubPixel::ALL )
            accum.transfer = false;

        accum.stepsDone = LB_MAX( accum.stepsDone, subPixel.size *
                                  frame->getFrameData()->getContext().period );
    }

    applyBuffer();
    applyViewport();
    setupAssemblyState();

    try
    {
        eq::Compositor::assembleFrames( frames, this, accum.buffer.get( ));
    }
    catch( const co::Exception& e )
    {
        LBWARN << e.what() << std::endl;
    }

    resetAssemblyState();
}
コード例 #11
0
ファイル: renderer.cpp プロジェクト: ImpressionMe/Equalizer
void Renderer::updateNearFar( const Vector4f& boundingSphere )
{
    const Matrix4f& view = getViewMatrix();
    Matrix4f viewInv;
    compute_inverse( view, viewInv );

    const Vector3f& zero  = viewInv * Vector3f::ZERO;
    Vector3f        front = viewInv * Vector3f( 0.0f, 0.0f, -1.0f );
    front -= zero;
    front.normalize();
    front *= boundingSphere.w();

    const Vector3f& translation = getModelMatrix().get_translation();
    const Vector3f& center = translation - boundingSphere.get_sub_vector< 3 >();
    const Vector3f& nearPoint  = view * ( center - front );
    const Vector3f& farPoint   = view * ( center + front );

    if( _impl->useOrtho( ))
    {
        LBASSERTINFO( fabs( farPoint.z() - nearPoint.z() ) >
                      std::numeric_limits< float >::epsilon(),
                      nearPoint << " == " << farPoint );
        setNearFar( -nearPoint.z(), -farPoint.z() );
    }
    else
    {
        // estimate minimal value of near plane based on frustum size
        const eq::Frustumf& frustum = _impl->getFrustum();
        const float width  = fabs( frustum.right() - frustum.left() );
        const float height = fabs( frustum.top() - frustum.bottom() );
        const float size   = LB_MIN( width, height );
        const float minNear = frustum.near_plane() / size * .001f;

        const float zNear = LB_MAX( minNear, -nearPoint.z() );
        const float zFar  = LB_MAX( zNear * 2.f, -farPoint.z() );

        setNearFar( zNear, zFar );
    }
}
コード例 #12
0
ファイル: data.cpp プロジェクト: Eyescale/GLStats
    uint128_t computeMinMax() const
    {
        uint64_t xMax = 0;
        uint64_t xMin = std::numeric_limits<uint64_t>::max();

        for (ItemsCIter i = items.begin(); i != items.end(); ++i)
        {
            const Item& item = *i;
            xMin = LB_MIN(xMin, item.start);
            xMax = LB_MAX(xMax, item.end);
        }
        return uint128_t(xMax, xMin);
    }
コード例 #13
0
ファイル: CameraPath.cpp プロジェクト: hernando/Livre
bool CameraPath::loadAnimation( const std::string& fileName )
{
    steps_.clear();

    if( fileName.empty( ) )
        return false;

    std::ifstream file;
    file.open( fileName.c_str( ));
    if( !file )
    {
        LBERROR << "Path file could not be opened" << std::endl;
        return false;
    }

    // read model pre-rotation
    file >> modelRotation_.x();
    file >> modelRotation_.y();
    file >> modelRotation_.z();

    const float m = static_cast< float >( M_PI_2 ) / 90.f;
    modelRotation_ *= m;

    uint32_t count = 0;
    float v[7];
    totalFrameNumber_ = 0;
    while ( !file.eof( ))
    {
        file >> v[ count++ ];
        if( count == 7 )
        {
            count = 0;
            totalFrameNumber_ += LB_MAX( static_cast<int>( v[0] ), 1 );

            steps_.push_back( Step( totalFrameNumber_,
                              Vector3f(  v[1]  , v[2]  , v[3]   ),
                              Vector3f( -v[5]*m, v[4]*m, v[6]*m )));
        }
    }
    file.close();

    return true;
}
コード例 #14
0
ファイル: oCommand.cpp プロジェクト: 4Second2None/Collage
void OCommand::sendData( const void* buffer, const uint64_t size,
                         const bool last )
{
    LBASSERT( !_impl->dispatcher );
    LBASSERT( last );
    LBASSERTINFO( size >= 16, size );
    LBASSERT( getBuffer().getData() == buffer );
    LBASSERT( getBuffer().getSize() == size );
    LBASSERT( getBuffer().getMaxSize() >= COMMAND_MINSIZE );

    // Update size field
    uint8_t* bytes = getBuffer().getData();
    reinterpret_cast< uint64_t* >( bytes )[ 0 ] = _impl->size + size;
    const uint64_t sendSize = _impl->isLocked ? size : LB_MAX( size,
                                                               COMMAND_MINSIZE);
    const Connections& connections = getConnections();
    for( ConnectionsCIter i = connections.begin(); i != connections.end(); ++i )
    {
        ConnectionPtr connection = *i;
        connection->send( bytes, sendSize, _impl->isLocked );
    }
}
コード例 #15
0
ファイル: pipe.cpp プロジェクト: niujunpenghn/Equalizer
bool Pipe::_cmdFrameStart( co::ICommand& cmd )
{
    LB_TS_THREAD( _pipeThread );

    co::ObjectICommand command( cmd );
    const uint128_t version = command.get< uint128_t >();
    const uint128_t frameID = command.get< uint128_t >();
    const uint32_t frameNumber = command.get< uint32_t >();

    LBVERB << "handle pipe frame start " << command << " frame " << frameNumber
           << " id " << frameID << std::endl;

    LBLOG( LOG_TASKS ) << "---- TASK start frame ---- frame " << frameNumber
                       << " id " << frameID << std::endl;
    sync( version );
    const int64_t lastFrameTime = _impl->frameTime;

    _impl->frameTimeMutex.set();
    LBASSERT( !_impl->frameTimes.empty( ));

    _impl->frameTime = _impl->frameTimes.front();
    _impl->frameTimes.pop_front();
    _impl->frameTimeMutex.unset();

    if( lastFrameTime > 0 )
    {
        PipeStatistics waitEvent( Statistic::PIPE_IDLE, this );
        waitEvent.event.statistic.idleTime =
            _impl->thread ? _impl->thread->getWorkerQueue()->resetWaitTime() :0;
        waitEvent.event.statistic.totalTime =
            LB_MAX( _impl->frameTime - lastFrameTime, 1 ); // avoid SIGFPE
    }

    LBASSERTINFO( _impl->currentFrame + 1 == frameNumber,
                  "current " <<_impl->currentFrame << " start " << frameNumber);

    frameStart( frameID, frameNumber );
    return true;
}
コード例 #16
0
void FramerateEqualizer::notifyUpdatePre( Compound* compound,
        const uint32_t frameNumber )
{
    _init();

    // find starting point of contiguous block
    const ssize_t size = static_cast< ssize_t >( _times.size( ));
    ssize_t       from = 0;
    if( size > 0 )
    {
        for( ssize_t i = size-1; i >= 0; --i )
        {
            if( _times[i].second != 0.f )
                continue;

            from = i;
            break;
        }
    }

    // find max / avg time in block
    size_t nSamples = 0;
#ifdef USE_AVERAGE
    float sumTime = 0.f;
#else
    float maxTime  = 0.f;
#endif

    for( ++from; from < size && nSamples < _nSamples; ++from )
    {
        const FrameTime& time = _times[from];
        LBASSERT( time.first > 0 );
        LBASSERT( time.second != 0.f );

        ++nSamples;
#ifdef USE_AVERAGE
        sumTime += time.second;
#else
        maxTime = LB_MAX( maxTime, time.second );
#endif
        LBLOG( LOG_LB2 ) << "Using " << time.first << ", " << time.second
                         << "ms" << std::endl;
    }

    if( nSamples == _nSamples )       // If we have a full set
        while( from < static_cast< ssize_t >( _times.size( )))
            _times.pop_back();            //  delete all older samples

    if( isFrozen() || !compound->isActive() || !isActive( ))
    {
        // always execute code above to not leak memory
        compound->setMaxFPS( std::numeric_limits< float >::max( ));
        return;
    }

    if( nSamples > 0 )
    {
        //TODO: totalTime *= 1.f - damping;
#ifdef USE_AVERAGE
        const float time = (sumTime / nSamples) * SLOWDOWN;
#else
        const float time = maxTime * SLOWDOWN;
#endif

        const float fps = 1000.f / time;
#ifdef VSYNC_CAP
        if( fps > VSYNC_CAP )
            compound->setMaxFPS( std::numeric_limits< float >::max( ));
        else
#endif
            compound->setMaxFPS( fps );

        LBLOG( LOG_LB2 ) << fps << " Hz from " << nSamples << "/"
                         << _times.size() << " samples, " << time << "ms"
                         << std::endl;
    }

    _times.push_front( FrameTime( frameNumber, 0.f ));
    LBASSERT( _times.size() < 210 );
}
コード例 #17
0
ファイル: config.cpp プロジェクト: steiner-/Equalizer
bool Config::handleEvent( eq::EventICommand command )
{
    switch( command.getEventType( ))
    {
        case eq::Event::KEY_PRESS:
        {
            const eq::Event& event = command.get< eq::Event >();
            if( _handleKeyEvent( event.keyPress ))
            {
                _redraw = true;
                return true;
            }
            break;
        }

        case eq::Event::CHANNEL_POINTER_BUTTON_PRESS:
        {
            const eq::Event& event = command.get< eq::Event >();
            const eq::uint128_t& viewID = event.context.view.identifier;
            _frameData.setCurrentViewID( viewID );
            if( viewID == 0 )
            {
                _currentCanvas = 0;
                return false;
            }

            const View* view = _getCurrentView();
            const eq::Layout* layout = view->getLayout();
            const eq::Canvases& canvases = getCanvases();
            for( eq::CanvasesCIter i = canvases.begin();
                 i != canvases.end(); ++i )
            {
                eq::Canvas* canvas = *i;
                const eq::Layout* canvasLayout = canvas->getActiveLayout();

                if( canvasLayout == layout )
                {
                    _currentCanvas = canvas;
                    return true;
                }
            }
            return true;
        }

        case eq::Event::CHANNEL_POINTER_BUTTON_RELEASE:
        {
            const eq::Event& event = command.get< eq::Event >();
            const eq::PointerEvent& releaseEvent =
                event.pointerButtonRelease;
            if( releaseEvent.buttons == eq::PTR_BUTTON_NONE)
            {
                if( releaseEvent.button == eq::PTR_BUTTON1 )
                {
                    _spinX = releaseEvent.dy;
                    _spinY = releaseEvent.dx;
                    _redraw = true;
                    return true;
                }
                if( releaseEvent.button == eq::PTR_BUTTON2 )
                {
                    _advance = -releaseEvent.dy;
                    _redraw = true;
                    return true;
                }
            }
            break;
        }
        case eq::Event::CHANNEL_POINTER_MOTION:
        {
            const eq::Event& event = command.get< eq::Event >();
            switch( event.pointerMotion.buttons )
            {
              case eq::PTR_BUTTON1:
                  _spinX = 0;
                  _spinY = 0;

                  if( _frameData.usePilotMode())
                      _frameData.spinCamera(
                          -0.005f * event.pointerMotion.dy,
                          -0.005f * event.pointerMotion.dx );
                  else
                      _frameData.spinModel(
                          -0.005f * event.pointerMotion.dy,
                          -0.005f * event.pointerMotion.dx, 0.f );
                  _redraw = true;
                  return true;

              case eq::PTR_BUTTON2:
                  _advance = -event.pointerMotion.dy;
                  _frameData.moveCamera( 0.f, 0.f, .005f * _advance );
                  _redraw = true;
                  return true;

              case eq::PTR_BUTTON3:
                  _frameData.moveCamera(  .0005f * event.pointerMotion.dx,
                                         -.0005f * event.pointerMotion.dy,
                                          0.f );
                  _redraw = true;
                  return true;
            }
            break;
        }

        case eq::Event::CHANNEL_POINTER_WHEEL:
        {
            const eq::Event& event = command.get< eq::Event >();
            _frameData.moveCamera( -0.05f * event.pointerWheel.yAxis,
                                   0.f,
                                   0.05f * event.pointerWheel.xAxis );
            _redraw = true;
            return true;
        }

        case eq::Event::MAGELLAN_AXIS:
        {
            const eq::Event& event = command.get< eq::Event >();
            _spinX = 0;
            _spinY = 0;
            _advance = 0;
            _frameData.spinModel( 0.0001f * event.magellan.xRotation,
                                  0.0001f * event.magellan.yRotation,
                                  0.0001f * event.magellan.zRotation );
            _frameData.moveCamera( 0.0001f * event.magellan.xAxis,
                                   0.0001f * event.magellan.yAxis,
                                   0.0001f * event.magellan.zAxis );
            _redraw = true;
            return true;
        }

        case eq::Event::MAGELLAN_BUTTON:
        {
            const eq::Event& event = command.get< eq::Event >();
            if( event.magellan.button == eq::PTR_BUTTON1 )
                _frameData.toggleColorMode();

            _redraw = true;
            return true;
        }

        case eq::Event::WINDOW_EXPOSE:
        case eq::Event::WINDOW_RESIZE:
        case eq::Event::WINDOW_CLOSE:
        case eq::Event::VIEW_RESIZE:
            _redraw = true;
            break;

        case IDLE_AA_LEFT:
            if( _useIdleAA )
            {
                const int32_t steps = command.get< int32_t >();
                _numFramesAA = LB_MAX( _numFramesAA, steps );
            }
            else
                _numFramesAA = 0;
            return false;

        default:
            break;
    }

    _redraw |= eq::Config::handleEvent( command );
    return _redraw;
}
コード例 #18
0
ファイル: viewEqualizer.cpp プロジェクト: Eyescale/Equalizer
void ViewEqualizer::Listener::notifyLoadData(Channel* channel,
                                             const uint32_t frameNumber,
                                             const Statistics& statistics,
                                             const Viewport& /*region*/)
{
    Load& load = _getLoad(frameNumber);
    if (load == Load::NONE)
        return;

    LBASSERT(_taskIDs.find(channel) != _taskIDs.end());
    const uint32_t taskID = _taskIDs[channel];

    // gather relevant load data
    int64_t startTime = std::numeric_limits<int64_t>::max();
    int64_t endTime = 0;
    bool loadSet = false;
    int64_t transmitTime = 0;
    for (size_t i = 0; i < statistics.size() && !loadSet; ++i)
    {
        const Statistic& data = statistics[i];
        if (data.task != taskID) // data from another compound
            continue;

        switch (data.type)
        {
        case Statistic::CHANNEL_CLEAR:
        case Statistic::CHANNEL_DRAW:
        case Statistic::CHANNEL_READBACK:
            startTime = LB_MIN(startTime, data.startTime);
            endTime = LB_MAX(endTime, data.endTime);
            break;

        case Statistic::CHANNEL_ASYNC_READBACK:
        case Statistic::CHANNEL_FRAME_TRANSMIT:
            transmitTime += data.startTime - data.endTime;
            break;
        case Statistic::CHANNEL_FRAME_WAIT_SENDTOKEN:
            transmitTime -= data.endTime - data.startTime;
            break;

        // assemble blocks on input frames, stop using subsequent data
        case Statistic::CHANNEL_ASSEMBLE:
            loadSet = true;
            break;

        default:
            break;
        }
    }

    if (startTime == std::numeric_limits<int64_t>::max())
        return;

    LBASSERTINFO(load.missing > 0, load << " for " << channel->getName() << " "
                                        << channel->getSerial());

    const int64_t time = LB_MAX(endTime - startTime, transmitTime);
    load.time += time;
    --load.missing;

    if (load.missing == 0)
    {
        const float rTime = float(load.time) / float(load.nResources);
        load.time = int64_t(rTime * sqrtf(float(load.nResources)));
    }

    LBLOG(LOG_LB1) << "Task " << taskID << ", added time " << time << " to "
                   << load << " from " << channel->getName() << " "
                   << channel->getSerial() << std::endl;
}
コード例 #19
0
void LoadEqualizer::_computeSplit( Node* node, const float time,
                                   LBDatas* datas, const Viewport& vp,
                                   const Range& range )
{
    LBLOG( LOG_LB2 ) << "_computeSplit " << vp << ", " << range << " time "
                    << time << std::endl;
    LBASSERTINFO( vp.isValid(), vp );
    LBASSERTINFO( range.isValid(), range );
    LBASSERTINFO( node->resources > 0.f || !vp.hasArea() || !range.hasData(),
                  "Assigning " << node->resources <<
                  " work to viewport " << vp << ", " << range );

    Compound* compound = node->compound;
    if( compound )
    {
        _assign( compound, vp, range );
        return;
    }

    LBASSERT( node->left && node->right );

    LBDatas workingSet = datas[ node->mode ];
    const float leftTime = node->resources > 0 ?
                           time * node->left->resources / node->resources : 0.f;
    float timeLeft = LB_MIN( leftTime, time ); // correct for fp rounding error

    switch( node->mode )
    {
        case MODE_VERTICAL:
        {
            LBASSERT( range == Range::ALL );

            float splitPos = vp.x;
            const float end = vp.getXEnd();

            while( timeLeft > std::numeric_limits< float >::epsilon() &&
                   splitPos < end )
            {
                LBLOG( LOG_LB2 ) << timeLeft << "ms left using "
                                << workingSet.size() << " tiles" << std::endl;

                // remove all irrelevant items from working set
                for( LBDatas::iterator i = workingSet.begin();
                     i != workingSet.end(); )
                {
                    const Data& data = *i;
                    if( data.vp.getXEnd() > splitPos )
                        ++i;
                    else
                        i = workingSet.erase( i );
                }
                if( workingSet.empty( ))
                    break;

                // find next 'discontinouity' in loads
                float currentPos = 1.0f;
                for( LBDatas::const_iterator i = workingSet.begin();
                     i != workingSet.end(); ++i )
                {
                    const Data& data = *i;
                    if( data.vp.x > splitPos && data.vp.x < currentPos )
                        currentPos = data.vp.x;
                    const float xEnd = data.vp.getXEnd();
                    if( xEnd > splitPos && xEnd < currentPos )
                        currentPos = xEnd;
                }

                const float width = currentPos - splitPos;
                LBASSERTINFO( width > 0.f, currentPos << "<=" << splitPos );
                LBASSERT( currentPos <= 1.0f );

                // accumulate normalized load in splitPos...currentPos
                LBLOG( LOG_LB2 ) << "Computing load in X " << splitPos << "..."
                                 << currentPos << std::endl;
                float currentTime = 0.f;
                for( LBDatas::const_iterator i = workingSet.begin();
                     i != workingSet.end(); ++i )
                {
                    const Data& data = *i;

                    if( data.vp.x >= currentPos ) // not yet needed data sets
                        break;

                    float yContrib = data.vp.h;
                    if( data.vp.y < vp.y )
                        yContrib -= (vp.y - data.vp.y);

                    const float dataEnd = data.vp.getYEnd();
                    const float vpEnd   = vp.getYEnd();
                    if( dataEnd > vpEnd )
                        yContrib -= (dataEnd - vpEnd);

                    if( yContrib > 0.f )
                    {
                        const float percentage = ( width / data.vp.w ) *
                                                 ( yContrib / data.vp.h );
                        currentTime += ( data.time * percentage );

                        LBLOG( LOG_LB2 ) << data.vp << " contributes "
                                         << yContrib << " in " << vp.h << " ("
                                         << percentage << ") with " << data.time
                                         << ": " << ( data.time * percentage )
                                         << " vp.y " << vp.y << " dataEnd "
                                         << dataEnd << " vpEnd " << vpEnd
                                         << std::endl;
                        LBASSERT( percentage < 1.01f )
                    }
                }

                LBLOG( LOG_LB2 ) << splitPos << "..." << currentPos << ": t="
                                 << currentTime << " of " << timeLeft
                                 << std::endl;

                if( currentTime >= timeLeft ) // found last region
                {
                    splitPos += ( width * timeLeft / currentTime );
                    timeLeft = 0.0f;
                }
                else
                {
                    timeLeft -= currentTime;
                    splitPos  = currentPos;
                }
            }

            LBLOG( LOG_LB2 ) << "Should split at X " << splitPos << std::endl;
            if( getDamping() < 1.f )
                splitPos = (1.f - getDamping()) * splitPos +
                            getDamping() * node->split;
            LBLOG( LOG_LB2 ) << "Dampened split at X " << splitPos << std::endl;

            // There might be more time left due to MIN_PIXEL rounding by parent
            // LBASSERTINFO( timeLeft <= .001f, timeLeft );

            // Ensure minimum size
            const Compound* root = getCompound();
            const float pvpW = static_cast< float >(
                root->getInheritPixelViewport().w );
            const float boundary = static_cast< float >( node->boundary2i.x()) /
                                       pvpW;
            if( node->left->resources == 0.f )
                splitPos = vp.x;
            else if( node->right->resources == 0.f )
                splitPos = end;
            else if( boundary > 0 )
            {
                const float lengthRight = vp.getXEnd() - splitPos;
                const float lengthLeft = splitPos - vp.x;
                const float maxRight =
                    static_cast< float >( node->right->maxSize.x( )) / pvpW;
                const float maxLeft =
                    static_cast< float >( node->left->maxSize.x( )) / pvpW;
                if( lengthRight > maxRight )
                    splitPos = end - maxRight;
                else if( lengthLeft > maxLeft )
                    splitPos = vp.x + maxLeft;

                if( (splitPos - vp.x) < boundary )
                    splitPos = vp.x + boundary;
                if( (end - splitPos) < boundary )
                    splitPos = end - boundary;

                const uint32_t ratio =
                           static_cast< uint32_t >( splitPos / boundary + .5f );
                splitPos = ratio * boundary;
            }

            splitPos = LB_MAX( splitPos, vp.x );
            splitPos = LB_MIN( splitPos, end);

            const float newPixelW = pvpW * splitPos;
            const float oldPixelW = pvpW * node->split;
            if( int( fabs(newPixelW - oldPixelW) ) < node->resistance2i.x( ))
                splitPos = node->split;
            else
                node->split = splitPos;

            LBLOG( LOG_LB2 ) << "Constrained split " << vp << " at X "
                             << splitPos << std::endl;

            // balance children
            Viewport childVP = vp;
            childVP.w = (splitPos - vp.x);
            _computeSplit( node->left, leftTime, datas, childVP, range );

            childVP.x = childVP.getXEnd();
            childVP.w = end - childVP.x;
            // Fix 2994111: Rounding errors with 2D LB and 16 sources
            //   Floating point rounding may create a width for the 'right'
            //   child which is slightly below the parent width. Correct it.
            while( childVP.getXEnd() < end )
                childVP.w += std::numeric_limits< float >::epsilon();
            _computeSplit( node->right, time-leftTime, datas, childVP, range );
            break;
        }

        case MODE_HORIZONTAL:
        {
            LBASSERT( range == Range::ALL );
            float splitPos = vp.y;
            const float end = vp.getYEnd();

            while( timeLeft > std::numeric_limits< float >::epsilon() &&
                   splitPos < end )
            {
                LBLOG( LOG_LB2 ) << timeLeft << "ms left using "
                                 << workingSet.size() << " tiles" << std::endl;

                // remove all unrelevant items from working set
                for( LBDatas::iterator i = workingSet.begin();
                     i != workingSet.end(); )
                {
                    const Data& data = *i;
                    if( data.vp.getYEnd() > splitPos )
                        ++i;
                    else
                        i = workingSet.erase( i );
                }
                if( workingSet.empty( ))
                    break;

                // find next 'discontinuouity' in loads
                float currentPos = 1.0f;
                for( LBDatas::const_iterator i = workingSet.begin();
                     i != workingSet.end(); ++i )
                {
                    const Data& data = *i;
                    if( data.vp.y > splitPos && data.vp.y < currentPos )
                        currentPos = data.vp.y;
                    const float yEnd = data.vp.getYEnd();
                    if( yEnd > splitPos && yEnd < currentPos )
                        currentPos = yEnd;
                }

                const float height = currentPos - splitPos;
                LBASSERTINFO( height > 0.f, currentPos << "<=" << splitPos );
                LBASSERT( currentPos <= 1.0f );

                // accumulate normalized load in splitPos...currentPos
                LBLOG( LOG_LB2 ) << "Computing load in Y " << splitPos << "..."
                                << currentPos << std::endl;
                float currentTime = 0.f;
                for( LBDatas::const_iterator i = workingSet.begin();
                     i != workingSet.end(); ++i )
                {
                    const Data& data = *i;

                    if( data.vp.y >= currentPos ) // not yet needed data sets
                        break;

                    float xContrib = data.vp.w;

                    if( data.vp.x < vp.x )
                        xContrib -= (vp.x - data.vp.x);

                    const float dataEnd = data.vp.getXEnd();
                    const float vpEnd   = vp.getXEnd();
                    if( dataEnd > vpEnd )
                        xContrib -= (dataEnd - vpEnd);

                    if( xContrib > 0.f )
                    {
                        const float percentage = ( height / data.vp.h ) *
                                                 ( xContrib / data.vp.w );
                        currentTime += ( data.time * percentage );

                        LBLOG( LOG_LB2 ) << data.vp << " contributes "
                                         << xContrib << " in " << vp.w << " ("
                                         << percentage << ") with " << data.time
                                         << ": " << ( data.time * percentage )
                                         << " total " << currentTime << " vp.x "
                                         << vp.x << " dataEnd " << dataEnd
                                         << " vpEnd " << vpEnd << std::endl;
                        LBASSERT( percentage < 1.01f )
                    }
                }

                LBLOG( LOG_LB2 ) << splitPos << "..." << currentPos << ": t="
                                 << currentTime << " of " << timeLeft
                                 << std::endl;

                if( currentTime >= timeLeft ) // found last region
                {
                    splitPos += (height * timeLeft / currentTime );
                    timeLeft = 0.0f;
                }
                else
                {
                    timeLeft -= currentTime;
                    splitPos  = currentPos;
                }
            }

            LBLOG( LOG_LB2 ) << "Should split at Y " << splitPos << std::endl;
            if( getDamping() < 1.f )
                splitPos = (1.f - getDamping( )) * splitPos +
                            getDamping() * node->split;
            LBLOG( LOG_LB2 ) << "Dampened split at Y " << splitPos << std::endl;

            const Compound* root = getCompound();

            const float pvpH = static_cast< float >(
                root->getInheritPixelViewport().h );
            const float boundary = static_cast< float >(node->boundary2i.y( )) /
                                       pvpH;

            if( node->left->resources == 0.f )
                splitPos = vp.y;
            else if( node->right->resources == 0.f )
                splitPos = end;
            else if ( boundary > 0 )
            {
                const float lengthRight = vp.getYEnd() - splitPos;
                const float lengthLeft = splitPos - vp.y;
                const float maxRight =
                    static_cast< float >( node->right->maxSize.y( )) / pvpH;
                const float maxLeft =
                    static_cast< float >( node->left->maxSize.y( )) / pvpH;
                if( lengthRight > maxRight )
                    splitPos = end - maxRight;
                else if( lengthLeft > maxLeft )
                    splitPos = vp.y + maxLeft;

                if( (splitPos - vp.y) < boundary )
                    splitPos = vp.y + boundary;
                if( (end - splitPos) < boundary )
                    splitPos = end - boundary;

                const uint32_t ratio =
                           static_cast< uint32_t >( splitPos / boundary + .5f );
                splitPos = ratio * boundary;
            }

            splitPos = LB_MAX( splitPos, vp.y );
            splitPos = LB_MIN( splitPos, end );

            const float newPixelH = pvpH * splitPos;
            const float oldPixelH = pvpH * node->split;
            if( int( fabs(newPixelH - oldPixelH) ) < node->resistance2i.y( ))
                splitPos = node->split;
            else
                node->split = splitPos;

            LBLOG( LOG_LB2 ) << "Constrained split " << vp << " at Y "
                             << splitPos << std::endl;

            Viewport childVP = vp;
            childVP.h = (splitPos - vp.y);
            _computeSplit( node->left, leftTime, datas, childVP, range );

            childVP.y = childVP.getYEnd();
            childVP.h = end - childVP.y;
            while( childVP.getYEnd() < end )
                childVP.h += std::numeric_limits< float >::epsilon();
            _computeSplit( node->right, time - leftTime, datas, childVP, range);
            break;
        }

        case MODE_DB:
        {
            LBASSERT( vp == Viewport::FULL );
            float splitPos = range.start;
            const float end = range.end;

            while( timeLeft > std::numeric_limits< float >::epsilon() &&
                   splitPos < end )
            {
                LBLOG( LOG_LB2 ) << timeLeft << "ms left using "
                                 << workingSet.size() << " tiles" << std::endl;

                // remove all irrelevant items from working set
                for( LBDatas::iterator i = workingSet.begin();
                     i != workingSet.end(); )
                {
                    const Data& data = *i;
                    if( data.range.end > splitPos )
                        ++i;
                    else
                        i = workingSet.erase( i );
                }
                if( workingSet.empty( ))
                    break;

                // find next 'discontinouity' in loads
                float currentPos = 1.0f;
                for( LBDatas::const_iterator i = workingSet.begin();
                     i != workingSet.end(); ++i )
                {
                    const Data& data = *i;
                    currentPos = LB_MIN( currentPos, data.range.end );
                }

                const float size = currentPos - splitPos;
                LBASSERTINFO( size > 0.f, currentPos << "<=" << splitPos );
                LBASSERT( currentPos <= 1.0f );

                // accumulate normalized load in splitPos...currentPos
                LBLOG( LOG_LB2 ) << "Computing load in range " << splitPos
                                << "..." << currentPos << std::endl;
                float currentTime = 0.f;
                for( LBDatas::const_iterator i = workingSet.begin();
                     i != workingSet.end(); ++i )
                {
                    const Data& data = *i;

                    if( data.range.start >= currentPos ) // not yet needed data
                        break;
#if 0
                    // make sure we cover full area
                    LBASSERTINFO(  data.range.start <= splitPos,
                                   data.range.start << " > " << splitPos );
                    LBASSERTINFO( data.range.end >= currentPos,
                                  data.range.end << " < " << currentPos);
#endif
                    currentTime += data.time * size / data.range.getSize();
                }

                LBLOG( LOG_LB2 ) << splitPos << "..." << currentPos << ": t="
                                 << currentTime << " of " << timeLeft
                                 << std::endl;

                if( currentTime >= timeLeft ) // found last region
                {
                    const float width = currentPos - splitPos;
                    splitPos += (width * timeLeft / currentTime );
                    timeLeft = 0.0f;
                }
                else
                {
                    timeLeft -= currentTime;
                    splitPos  = currentPos;
                }
            }
            LBLOG( LOG_LB2 ) << "Should split at " << splitPos << std::endl;
            if( getDamping() < 1.f )
                splitPos = (1.f - getDamping( )) * splitPos +
                            getDamping() * node->split;
            LBLOG( LOG_LB2 ) << "Dampened split at " << splitPos << std::endl;

            const float boundary( node->boundaryf );
            if( node->left->resources == 0.f )
                splitPos = range.start;
            else if( node->right->resources == 0.f )
                splitPos = end;

            const uint32_t ratio = static_cast< uint32_t >
                      ( splitPos / boundary + .5f );
            splitPos = ratio * boundary;
            if( (splitPos - range.start) < boundary )
                splitPos = range.start;
            if( (end - splitPos) < boundary )
                splitPos = end;

            if( fabs( splitPos - node->split ) < node->resistancef )
                splitPos = node->split;
            else
                node->split = splitPos;

            LBLOG( LOG_LB2 ) << "Constrained split " << range << " at pos "
                             << splitPos << std::endl;

            Range childRange = range;
            childRange.end = splitPos;
            _computeSplit( node->left, leftTime, datas, vp, childRange );

            childRange.start = childRange.end;
            childRange.end   = range.end;
            _computeSplit( node->right, time - leftTime, datas, vp, childRange);
            break;
        }

        default:
            LBUNIMPLEMENTED;
    }
}
コード例 #20
0
void LoadEqualizer::_updateNode( Node* node, const Viewport& vp,
                                 const Range& range )
{
    Node* left = node->left;
    Node* right = node->right;

    LBASSERT( left );
    LBASSERT( right );

    Viewport leftVP = vp;
    Viewport rightVP = vp;
    Range leftRange = range;
    Range rightRange = range;

    switch( node->mode )
    {
      default:
        LBUNIMPLEMENTED;

      case MODE_VERTICAL:
        leftVP.w = vp.w * .5f;
        rightVP.x = leftVP.getXEnd();
        rightVP.w = vp.getXEnd() - rightVP.x;
        node->split = leftVP.getXEnd();
        break;

      case MODE_HORIZONTAL:
        leftVP.h = vp.h * .5f;
        rightVP.y = leftVP.getYEnd();
        rightVP.h = vp.getYEnd() - rightVP.y;
        node->split = leftVP.getYEnd();
        break;

      case MODE_DB:
        leftRange.end = range.start + ( range.end - range.start ) * .5f;
        rightRange.start = leftRange.end;
        node->split = leftRange.end;
        break;
    }

    _update( left, leftVP, leftRange );
    _update( right, rightVP, rightRange );

    node->resources = left->resources + right->resources;

    if( left->resources == 0.f )
    {
        node->maxSize    = right->maxSize;
        node->boundary2i = right->boundary2i;
        node->boundaryf  = right->boundaryf;
        node->resistance2i = right->resistance2i;
        node->resistancef = right->resistancef;
    }
    else if( right->resources == 0.f )
    {
        node->maxSize = left->maxSize;
        node->boundary2i = left->boundary2i;
        node->boundaryf = left->boundaryf;
        node->resistance2i = left->resistance2i;
        node->resistancef = left->resistancef;
    }
    else
    {
        switch( node->mode )
        {
        case MODE_VERTICAL:
            node->maxSize.x() = left->maxSize.x() + right->maxSize.x();
            node->maxSize.y() = LB_MIN( left->maxSize.y(), right->maxSize.y());
            node->boundary2i.x() = left->boundary2i.x()+ right->boundary2i.x();
            node->boundary2i.y() = LB_MAX( left->boundary2i.y(),
                                           right->boundary2i.y());
            node->boundaryf = LB_MAX( left->boundaryf, right->boundaryf );
            node->resistance2i.x() = LB_MAX( left->resistance2i.x(),
                                             right->resistance2i.x( ));
            node->resistance2i.y() = LB_MAX( left->resistance2i.y(),
                                             right->resistance2i.y());
            node->resistancef = LB_MAX( left->resistancef, right->resistancef );
            break;
        case MODE_HORIZONTAL:
            node->maxSize.x() = LB_MIN( left->maxSize.x(), right->maxSize.x());
            node->maxSize.y() = left->maxSize.y() + right->maxSize.y();
            node->boundary2i.x() = LB_MAX( left->boundary2i.x(),
                                           right->boundary2i.x() );
            node->boundary2i.y() = left->boundary2i.y()+ right->boundary2i.y();
            node->boundaryf = LB_MAX( left->boundaryf, right->boundaryf );
            node->resistance2i.x() = LB_MAX( left->resistance2i.x(),
                                             right->resistance2i.x() );
            node->resistance2i.y() = LB_MAX( left->resistance2i.y(),
                                             right->resistance2i.y( ));
            node->resistancef = LB_MAX( left->resistancef, right->resistancef );
            break;
        case MODE_DB:
            node->boundary2i.x() = LB_MAX( left->boundary2i.x(),
                                           right->boundary2i.x() );
            node->boundary2i.y() = LB_MAX( left->boundary2i.y(),
                                           right->boundary2i.y() );
            node->boundaryf = left->boundaryf + right->boundaryf;
            node->resistance2i.x() = LB_MAX( left->resistance2i.x(),
                                             right->resistance2i.x() );
            node->resistance2i.y() = LB_MAX( left->resistance2i.y(),
                                             right->resistance2i.y() );
            node->resistancef = LB_MAX( left->resistancef, right->resistancef );
            break;
        default:
            LBUNIMPLEMENTED;
        }
    }
}
コード例 #21
0
void LoadEqualizer::notifyLoadData( Channel* channel,
                                    const uint32_t frameNumber,
                                    const Statistics& statistics,
                                    const Viewport& region )
{
    LBLOG( LOG_LB2 ) << statistics.size()
                     << " samples from "<< channel->getName()
                     << " @ " << frameNumber << std::endl;
    for( std::deque< LBFrameData >::iterator i = _history.begin();
         i != _history.end(); ++i )
    {
        LBFrameData& frameData = *i;
        if( frameData.first != frameNumber )
            continue;

        // Found corresponding historical data set
        LBDatas& items = frameData.second;
        for( LBDatas::iterator j = items.begin(); j != items.end(); ++j )
        {
            Data& data = *j;
            if( data.channel != channel )
                continue;

            // Found corresponding historical data item
            const uint32_t taskID = data.taskID;
            LBASSERTINFO( taskID > 0, channel->getName( ));

            // gather relevant load data
            int64_t startTime = std::numeric_limits< int64_t >::max();
            int64_t endTime   = 0;
            bool    loadSet   = false;
            int64_t transmitTime = 0;
            for( size_t k = 0; k < statistics.size(); ++k )
            {
                const Statistic& stat = statistics[k];
                if( stat.task == data.destTaskID )
                    _updateAssembleTime( data, stat );

                // from different compound
                if( stat.task != taskID || loadSet )
                    continue;

                switch( stat.type )
                {
                case Statistic::CHANNEL_CLEAR:
                case Statistic::CHANNEL_DRAW:
                case Statistic::CHANNEL_READBACK:
                    startTime = LB_MIN( startTime, stat.startTime );
                    endTime   = LB_MAX( endTime, stat.endTime );
                    break;

                case Statistic::CHANNEL_ASYNC_READBACK:
                case Statistic::CHANNEL_FRAME_TRANSMIT:
                    transmitTime += stat.endTime - stat.startTime;
                    break;
                case Statistic::CHANNEL_FRAME_WAIT_SENDTOKEN:
                    transmitTime -= stat.endTime - stat.startTime;
                    break;

                // assemble blocks on input frames, stop using subsequent data
                case Statistic::CHANNEL_ASSEMBLE:
                    loadSet = true;
                    break;

                default:
                    break;
                }
            }

            if( startTime == std::numeric_limits< int64_t >::max( ))
                return;

            data.vp.apply( region ); // Update ROI
            data.time = endTime - startTime;
            data.time = LB_MAX( data.time, 1 );
            data.time = LB_MAX( data.time, transmitTime );
            data.assembleTime = LB_MAX( data.assembleTime, 0 );
            LBLOG( LOG_LB2 ) << "Added time " << data.time << " (+"
                             << data.assembleTime << ") for "
                             << channel->getName() << " " << data.vp << ", "
                             << data.range << " @ " << frameNumber << std::endl;
            return;

            // Note: if the same channel is used twice as a child, the
            // load-compound association does not work.
        }
    }
}
コード例 #22
0
ファイル: channel.cpp プロジェクト: BillTheBest/Equalizer
void Channel::frameDraw( const eq::uint128_t& frameID )
{
    if( stopRendering( ))
        return;

    _initJitter();
    if( _isDone( ))
        return;

    Window* window = static_cast< Window* >( getWindow( ));
    VertexBufferState& state = window->getState();
    const Model* oldModel = _model;
    const Model* model = _getModel();

    if( oldModel != model )
        state.setFrustumCulling( false ); // create all display lists/VBOs

    if( model )
        _updateNearFar( model->getBoundingSphere( ));

    eq::Channel::frameDraw( frameID ); // Setup OpenGL state

    glLightfv( GL_LIGHT0, GL_POSITION, lightPosition );
    glLightfv( GL_LIGHT0, GL_AMBIENT,  lightAmbient  );
    glLightfv( GL_LIGHT0, GL_DIFFUSE,  lightDiffuse  );
    glLightfv( GL_LIGHT0, GL_SPECULAR, lightSpecular );

    glMaterialfv( GL_FRONT, GL_AMBIENT,   materialAmbient );
    glMaterialfv( GL_FRONT, GL_DIFFUSE,   materialDiffuse );
    glMaterialfv( GL_FRONT, GL_SPECULAR,  materialSpecular );
    glMateriali(  GL_FRONT, GL_SHININESS, materialShininess );

    const FrameData& frameData = _getFrameData();
    glPolygonMode( GL_FRONT_AND_BACK,
                   frameData.useWireframe() ? GL_LINE : GL_FILL );

    const eq::Vector3f& position = frameData.getCameraPosition();

    glMultMatrixf( frameData.getCameraRotation().array );
    glTranslatef( position.x(), position.y(), position.z() );
    glMultMatrixf( frameData.getModelRotation().array );

    if( frameData.getColorMode() == COLOR_DEMO )
    {
        const eq::Vector3ub color = getUniqueColor();
        glColor3ub( color.r(), color.g(), color.b() );
    }
    else
        glColor3f( .75f, .75f, .75f );

    if( model )
        _drawModel( model );
    else
    {
        glNormal3f( 0.f, -1.f, 0.f );
        glBegin( GL_TRIANGLE_STRIP );
            glVertex3f(  .25f, 0.f,  .25f );
            glVertex3f( -.25f, 0.f,  .25f );
            glVertex3f(  .25f, 0.f, -.25f );
            glVertex3f( -.25f, 0.f, -.25f );
        glEnd();
    }

    state.setFrustumCulling( true );
    Accum& accum = _accum[ lunchbox::getIndexOfLastBit( getEye()) ];
    accum.stepsDone = LB_MAX( accum.stepsDone,
                              getSubPixel().size * getPeriod( ));
    accum.transfer = true;
}
コード例 #23
0
ファイル: treeEqualizer.cpp プロジェクト: bohara/Equalizer
void TreeEqualizer::_assign( Node* node, const Viewport& vp,
                             const Range& range )
{
    LBLOG( LOG_LB2 ) << "assign " << vp << ", " << range << " time "
                     << node->time << " split " << node->split << std::endl;
    LBASSERTINFO( vp.isValid(), vp );
    LBASSERTINFO( range.isValid(), range );
    LBASSERTINFO( node->resources > 0.f || !vp.hasArea() || !range.hasData(),
                  "Assigning work to unused compound: " << vp << ", " << range);

    Compound* compound = node->compound;
    if( compound )
    {
        LBASSERTINFO( vp == Viewport::FULL || range == Range::ALL,
                      "Mixed 2D/DB load-balancing not implemented" );

        compound->setViewport( vp );
        compound->setRange( range );
        LBLOG( LOG_LB2 ) << compound->getChannel()->getName() << " set " << vp
                         << ", " << range << std::endl;
        return;
    }

    switch( node->mode )
    {
    case MODE_VERTICAL:
    {
        // Ensure minimum size
        const Compound* root = getCompound();
        const float pvpW = float( root->getInheritPixelViewport().w );
        const float end = vp.getXEnd();
        const float boundary = float( node->boundary2i.x( )) / pvpW;
        float absoluteSplit = vp.x + vp.w * node->split;

        if( node->left->resources == 0.f )
            absoluteSplit = vp.x;
        else if( node->right->resources == 0.f )
            absoluteSplit = end;
        else if( boundary > 0 )
        {
            const float right = vp.getXEnd() - absoluteSplit;
            const float left = absoluteSplit - vp.x;
            const float maxRight = float( node->right->maxSize.x( )) / pvpW;
            const float maxLeft = float( node->left->maxSize.x( )) / pvpW;

            if( right > maxRight )
                absoluteSplit = end - maxRight;
            else if( left > maxLeft )
                absoluteSplit = vp.x + maxLeft;
            
            if( (absoluteSplit - vp.x) < boundary )
                absoluteSplit = vp.x + boundary;
            if( (end - absoluteSplit) < boundary )
                absoluteSplit = end - boundary;
                
            const uint32_t ratio = uint32_t( absoluteSplit / boundary + .5f );
            absoluteSplit = ratio * boundary;
        }

        absoluteSplit = LB_MAX( absoluteSplit, vp.x );
        absoluteSplit = LB_MIN( absoluteSplit, end);

        node->split = (absoluteSplit - vp.x ) / vp.w;
        LBLOG( LOG_LB2 ) << "Constrained split " << vp << " at X "
                         << node->split << std::endl;

        // traverse children
        Viewport childVP = vp;
        childVP.w = (absoluteSplit - vp.x);
        _assign( node->left, childVP, range );

        childVP.x = childVP.getXEnd();
        childVP.w = end - childVP.x;

        // Fix 2994111: Rounding errors with 2D LB and 16 sources
        //   Floating point rounding may create a width for the 'right'
        //   child which is slightly below the parent width. Correct it.
        while( childVP.getXEnd() < end )
            childVP.w += std::numeric_limits< float >::epsilon();

        _assign( node->right, childVP, range );
        break;
    }

    case MODE_HORIZONTAL:
    {
        // Ensure minimum size
        const Compound* root = getCompound();
        const float pvpH = float( root->getInheritPixelViewport().h );
        const float end = vp.getYEnd();
        const float boundary = float( node->boundary2i.y( )) / pvpH;
        float absoluteSplit = vp.y + vp.h * node->split;

        if( node->left->resources == 0.f )
            absoluteSplit = vp.y;
        else if( node->right->resources == 0.f )
            absoluteSplit = end;
        else if( boundary > 0 )
        {
            const float right = vp.getYEnd() - absoluteSplit;
            const float left = absoluteSplit - vp.y;
            const float maxRight = float( node->right->maxSize.y( )) / pvpH;
            const float maxLeft = float( node->left->maxSize.y( )) / pvpH;

            if( right > maxRight )
                absoluteSplit = end - maxRight;
            else if( left > maxLeft )
                absoluteSplit = vp.y + maxLeft;
            
            if( (absoluteSplit - vp.y) < boundary )
                absoluteSplit = vp.y + boundary;
            if( (end - absoluteSplit) < boundary )
                absoluteSplit = end - boundary;
                
            const uint32_t ratio = uint32_t( absoluteSplit / boundary + .5f );
            absoluteSplit = ratio * boundary;
        }

        absoluteSplit = LB_MAX( absoluteSplit, vp.y );
        absoluteSplit = LB_MIN( absoluteSplit, end);

        node->split = (absoluteSplit - vp.y ) / vp.h;
        LBLOG( LOG_LB2 ) << "Constrained split " << vp << " at X "
                         << node->split << std::endl;

        // traverse children
        Viewport childVP = vp;
        childVP.h = (absoluteSplit - vp.y);
        _assign( node->left, childVP, range );

        childVP.y = childVP.getYEnd();
        childVP.h = end - childVP.y;

        // Fix 2994111: Rounding errors with 2D LB and 16 sources
        //   Floating point rounding may create a width for the 'right'
        //   child which is slightly below the parent width. Correct it.
        while( childVP.getYEnd() < end )
            childVP.h += std::numeric_limits< float >::epsilon();

        _assign( node->right, childVP, range );
        break;
    }

    case MODE_DB:
    {
        LBASSERT( vp == Viewport::FULL );
        const float end = range.end;
        float absoluteSplit = range.start + (range.end-range.start)*node->split;

        const float boundary( node->boundaryf );
        if( node->left->resources == 0.f )
            absoluteSplit = range.start;
        else if( node->right->resources == 0.f )
            absoluteSplit = end;

        const uint32_t ratio = uint32_t( absoluteSplit / boundary + .5f );
        absoluteSplit = ratio * boundary;
        if( (absoluteSplit - range.start) < boundary )
            absoluteSplit = range.start;
        if( (end - absoluteSplit) < boundary )
            absoluteSplit = end;

        node->split = (absoluteSplit-range.start) / (range.end-range.start);
        LBLOG( LOG_LB2 ) << "Constrained split " << range << " at pos "
                         << node->split << std::endl;

        Range childRange = range;
        childRange.end = absoluteSplit;
        _assign( node->left, vp, childRange );

        childRange.start = childRange.end;
        childRange.end   = range.end;
        _assign( node->right, vp, childRange);
        break;
    }

    default:
        LBUNIMPLEMENTED;
    }
}
コード例 #24
0
ファイル: treeEqualizer.cpp プロジェクト: bohara/Equalizer
void TreeEqualizer::_update( Node* node )
{
    if( !node )
        return;

    const Compound* compound = node->compound;
    if( compound )
    {
        const Channel* channel = compound->getChannel();
        const PixelViewport& pvp = channel->getPixelViewport();
        LBASSERT( channel );

        node->resources = compound->isActive() ? compound->getUsage() : 0.f;
        node->maxSize.x() = pvp.w; 
        node->maxSize.y() = pvp.h; 
        node->boundaryf = _boundaryf;
        node->boundary2i = _boundary2i;
        return;
    }
    // else

    LBASSERT( node->left );
    LBASSERT( node->right );

    _update( node->left );
    _update( node->right );

    node->resources = node->left->resources + node->right->resources;

    if( node->left->resources == 0.f )
    {
        node->maxSize = node->right->maxSize;
        node->boundary2i = node->right->boundary2i;
        node->boundaryf = node->right->boundaryf;
        node->time = node->right->time;
    }
    else if( node->right->resources == 0.f )
    {
        node->maxSize = node->left->maxSize;
        node->boundary2i = node->left->boundary2i;
        node->boundaryf = node->left->boundaryf;
        node->time = node->left->time;
    }
    else
    {
        switch( node->mode )
        {
        case MODE_VERTICAL:
            node->maxSize.x() = node->left->maxSize.x() +
                                node->right->maxSize.x();  
            node->maxSize.y() = LB_MIN( node->left->maxSize.y(), 
                                        node->right->maxSize.y() ); 
            node->boundary2i.x() = node->left->boundary2i.x() +
                                   node->right->boundary2i.x();
            node->boundary2i.y() = LB_MAX( node->left->boundary2i.y(), 
                                           node->right->boundary2i.y());
            node->boundaryf = LB_MAX( node->left->boundaryf,
                                      node->right->boundaryf );
            break;
        case MODE_HORIZONTAL:
            node->maxSize.x() = LB_MIN( node->left->maxSize.x(), 
                                        node->right->maxSize.x() );  
            node->maxSize.y() = node->left->maxSize.y() +
                                node->right->maxSize.y(); 
            node->boundary2i.x() = LB_MAX( node->left->boundary2i.x(), 
                                           node->right->boundary2i.x() );
            node->boundary2i.y() = node->left->boundary2i.y() +
                                   node->right->boundary2i.y();
            node->boundaryf = LB_MAX( node->left->boundaryf,
                                      node->right->boundaryf );
            break;
        case MODE_DB:
            node->boundary2i.x() = LB_MAX( node->left->boundary2i.x(), 
                                           node->right->boundary2i.x() );
            node->boundary2i.y() = LB_MAX( node->left->boundary2i.y(), 
                                           node->right->boundary2i.y() );
            node->boundaryf = node->left->boundaryf +node->right->boundaryf;
            break;
        default:
            LBUNIMPLEMENTED;
        }

        node->time = node->left->time + node->right->time;
    }
}
コード例 #25
0
ファイル: fullMasterCM.cpp プロジェクト: tribal-tec/Collage
bool FullMasterCM::_initSlave( const MasterCMCommand& command,
                               const uint128_t& /*replyVersion*/,
                               bool replyUseCache )
{
    _checkConsistency();

    const uint128_t& version = command.getRequestedVersion();
    const uint128_t oldest = _instanceDatas.front()->os.getVersion();
    uint128_t start = (version == VERSION_OLDEST || version < oldest ) ?
                          oldest : version;
    uint128_t end = _version;

#ifndef NDEBUG
    if( version != VERSION_OLDEST && version < start )
        LBINFO << "Mapping version " << start << " instead of requested "
               << version << " for " << lunchbox::className( _object )
               << " " << ObjectVersion( _object->getID(), _version ) << " of "
               << _instanceDatas.size() << "/" << _nVersions << std::endl;
#endif

    const uint128_t& minCachedVersion = command.getMinCachedVersion();
    const uint128_t& maxCachedVersion = command.getMaxCachedVersion();
    const uint128_t replyVersion = start;
    if( replyUseCache )
    {
        if( minCachedVersion <= start && maxCachedVersion >= start )
        {
#ifdef CO_INSTRUMENT_MULTICAST
            _hit += maxCachedVersion + 1 - start;
#endif
            start = maxCachedVersion + 1;
        }
        else if( maxCachedVersion == end )
        {
            end = LB_MAX( start, minCachedVersion - 1 );
#ifdef CO_INSTRUMENT_MULTICAST
            _hit += _version - end;
#endif
        }
        // TODO else cached block in the middle, send head and tail elements
    }

#if 0
    LBLOG( LOG_OBJECTS )
        << *_object << ", instantiate on " << node->getNodeID() << " with v"
        << ((requested == VERSION_OLDEST) ? oldest : requested) << " ("
        << requested << ") sending " << start << ".." << end << " have "
        << _version - _nVersions << ".." << _version << " "
        << _instanceDatas.size() << std::endl;
#endif
    LBASSERT( start >= oldest );

    bool dataSent = false;

    // send all instance datas from start..end
    InstanceDataDeque::iterator i = _instanceDatas.begin();
    while( i != _instanceDatas.end() && (*i)->os.getVersion() < start )
        ++i;

    for( ; i != _instanceDatas.end() && (*i)->os.getVersion() <= end; ++i )
    {
        if( !dataSent )
        {
            _sendMapSuccess( command, true );
            dataSent = true;
        }

        InstanceData* data = *i;
        LBASSERT( data );
        data->os.sendMapData( command.getRemoteNode(),
                              command.getInstanceID( ));

#ifdef CO_INSTRUMENT_MULTICAST
        ++_miss;
#endif
    }

    if( !dataSent )
    {
        _sendMapSuccess( command, false );
        _sendMapReply( command, replyVersion, true, replyUseCache, false );
    }
    else
        _sendMapReply( command, replyVersion, true, replyUseCache, true );

#ifdef CO_INSTRUMENT_MULTICAST
    if( _miss % 100 == 0 )
        LBINFO << "Cached " << _hit << "/" << _hit + _miss
               << " instance data transmissions" << std::endl;
#endif
    return true;
}
コード例 #26
0
/*  Compute the bounding sphere of the leaf's indexed vertices.  */
const BoundingSphere& VertexBufferLeaf::updateBoundingSphere()
{
    // We determine a bounding sphere by:
    // 1) Using the inner sphere of the dominant axis of the bounding box as an
    //    estimate
    // 2) Test all points to be in that sphere
    // 3) Expand the sphere to contain all points outside.


    // 1a) initialize and compute a bounding box
    _boundingBox[0] = _globalData.vertices[ _vertexStart +
                                            _globalData.indices[_indexStart] ];
    _boundingBox[1] = _globalData.vertices[ _vertexStart +
                                            _globalData.indices[_indexStart] ];

    for( Index i = 1 + _indexStart; i < _indexStart + _indexLength; ++i )
    {
        const Vertex& vertex = _globalData.vertices[ _vertexStart +
                                                     _globalData.indices[ i ] ];
        _boundingBox[0][0] = std::min( _boundingBox[0][0], vertex[0] );
        _boundingBox[1][0] = std::max( _boundingBox[1][0], vertex[0] );
        _boundingBox[0][1] = std::min( _boundingBox[0][1], vertex[1] );
        _boundingBox[1][1] = std::max( _boundingBox[1][1], vertex[1] );
        _boundingBox[0][2] = std::min( _boundingBox[0][2], vertex[2] );
        _boundingBox[1][2] = std::max( _boundingBox[1][2], vertex[2] );
    }

    // 1b) get inner sphere of bounding box as an initial estimate
    _boundingSphere.x() = ( _boundingBox[0].x() + _boundingBox[1].x() ) * 0.5f;
    _boundingSphere.y() = ( _boundingBox[0].y() + _boundingBox[1].y() ) * 0.5f;
    _boundingSphere.z() = ( _boundingBox[0].z() + _boundingBox[1].z() ) * 0.5f;

    _boundingSphere.w()  = LB_MAX( _boundingBox[1].x() - _boundingBox[0].x(),
                                   _boundingBox[1].y() - _boundingBox[0].y() );
    _boundingSphere.w()  = LB_MAX( _boundingBox[1].z() - _boundingBox[0].z(),
                                   _boundingSphere.w() );
    _boundingSphere.w() *= .5f;

    float  radius        = _boundingSphere.w();
    float  radiusSquared =  radius * radius;
    Vertex center( _boundingSphere.array );

    // 2) test all points to be in the estimated bounding sphere
    for( Index offset = 0; offset < _indexLength; ++offset )
    {
        const Vertex& vertex =
            _globalData.vertices[ _vertexStart +
                                  _globalData.indices[_indexStart + offset] ];

        const Vertex centerToPoint   = vertex - center;
        const float  distanceSquared = centerToPoint.squared_length();
        if( distanceSquared <= radiusSquared ) // point is inside existing BS
            continue;

        // 3) expand sphere to contain 'outside' points
        const float distance = sqrtf( distanceSquared );
        const float delta    = distance - radius;

        radius        = ( radius + distance ) * .5f;
        radiusSquared = radius * radius;
        const Vertex normdelta = normalize( centerToPoint ) * ( 0.5f * delta );

        center       += normdelta;

        LBASSERTINFO( Vertex( vertex-center ).squared_length() <=
                ( radiusSquared + 2.f * std::numeric_limits<float>::epsilon( )),
                      vertex << " c " << center << " r " << radius << " ("
                             << Vertex( vertex-center ).length() << ")" );
    }

#ifndef NDEBUG
    // 2a) re-test all points to be in the estimated bounding sphere
    for( Index offset = 0; offset < _indexLength; ++offset )
    {
        const Vertex& vertex =
            _globalData.vertices[ _vertexStart +
                                  _globalData.indices[_indexStart + offset] ];

        const Vertex centerToPoint   = vertex - center;
        const float  distanceSquared = centerToPoint.squared_length();
        LBASSERTINFO( distanceSquared <=
                ( radiusSquared + 2.f * std::numeric_limits<float>::epsilon( )),
                      vertex << " c " << center << " r " << radius << " ("
                             << Vertex( vertex-center ).length() << ")" );
    }
#endif

    // store optimal bounding sphere
    _boundingSphere.x() = center.x();
    _boundingSphere.y() = center.y();
    _boundingSphere.z() = center.z();
    _boundingSphere.w() = radius;

#ifndef NDEBUG
    PLYLIBINFO << "updateBoundingSphere" << "( " << _boundingSphere << " )."
             << std::endl;
#endif

    return _boundingSphere;
}