Exemplo n.º 1
0
    /// Get the package loader to use to load the object with the given path, creating it if necessary.
    ///
    /// @param[in] path  Asset path.
    ///
    /// @return  Package loader to use to load the specified object.
    LoosePackageLoader* LoosePackageLoaderMap::GetPackageLoader( AssetPath path )
    {
        HELIUM_ASSERT( !path.IsEmpty() );

        // Resolve the object's package.
        AssetPath packagePath = path;
        while( !packagePath.IsPackage() )
        {
            packagePath = packagePath.GetParent();
            if( packagePath.IsEmpty() )
            {
                HELIUM_TRACE(
                    TraceLevels::Error,
                    ( TXT( "LoosePackageLoaderMap::GetPackageLoader(): Cannot resolve package loader for \"%s\", as it " )
                    TXT( "is not located in a package.\n" ) ),
                    *path.ToString() );

                return NULL;
            }
        }

        // Locate an existing package loader.
        ConcurrentHashMap< AssetPath, LoosePackageLoader* >::ConstAccessor constMapAccessor;
        if( m_packageLoaderMap.Find( constMapAccessor, packagePath ) )
        {
            LoosePackageLoader* pLoader = constMapAccessor->Second();
            HELIUM_ASSERT( pLoader );

            return pLoader;
        }

        // Add a new package loader entry.
        ConcurrentHashMap< AssetPath, LoosePackageLoader* >::Accessor mapAccessor;
        bool bInserted = m_packageLoaderMap.Insert(
            mapAccessor,
            KeyValue< AssetPath, LoosePackageLoader* >( packagePath, NULL ) );
        if( bInserted )
        {
            // Entry added, so create and initialize the package loader.
            LoosePackageLoader* pLoader = new LoosePackageLoader;
            HELIUM_ASSERT( pLoader );

            bool bInitResult = pLoader->Initialize( packagePath );
            HELIUM_ASSERT( bInitResult );
            if( !bInitResult )
            {
                HELIUM_TRACE(
                    TraceLevels::Error,
                    TXT( "LoosePackageLoaderMap::GetPackageLoader(): Failed to initialize package loader for \"%s\".\n" ),
                    *packagePath.ToString() );

                m_packageLoaderMap.Remove( mapAccessor );

                return NULL;
            }

            HELIUM_VERIFY( pLoader->BeginPreload() );

            mapAccessor->Second() = pLoader;
        }

        // PMD: I am not 100% sure this is all thread safe. I think it could break if:
        // - Thread 1 inserts a key/value of path and NULL, as above
        // - Thread 2 returns false from the insert so we come straight here
        //   - Thread 2 tries to use pLoader before thread 1 assigns ploader to the value of the key
        // Note: If we did not do this assert here, we could potentially get nulls from this same thread later when
        // trying to find pLoader.
        //
        // Leaving it alone for now since I'm not sure, but if this assert gets tripped, we need to revisit this.
        // Easy fix may be to allocate and construct (but don't completely init) an LoosePackageLoader, and try
        // to insert that directly rather than the null above. If insert succeeds, finish, else ditch our loader
        // and grab the one out of the array
        LoosePackageLoader* pLoader = mapAccessor->Second();
        HELIUM_ASSERT( pLoader );

        return pLoader;
    }
Exemplo n.º 2
0
int Helium::Execute( const tstring& command, tstring& output, bool showWindow )
{
    HANDLE hReadPipe;
    HANDLE hWritePipe;
    SECURITY_ATTRIBUTES sa;
    sa.nLength              = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle       = TRUE;
    if( !CreatePipe( &hReadPipe, &hWritePipe, &sa, 0 ) )
    {
        return -1;
    }

    STARTUPINFO          si;
    memset( &si, 0, sizeof(si) );
    si.cb          = sizeof(si);
    si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow = static_cast<int>( showWindow );
    si.hStdOutput  = hWritePipe;
    si.hStdError   = hWritePipe;      

    PROCESS_INFORMATION  pi;
    memset( &pi, 0, sizeof( pi ) );

    if( !CreateProcess(
        NULL,                                                 // filename
        (tchar_t*) command.c_str(),                           // command line for child
        NULL,                                                 // process security descriptor
        NULL,                                                 // thread security descriptor
        TRUE,                                                 // inherit handles?
        showWindow ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW,   // creation flags
        NULL,                                                 // inherited environment address
        NULL,                                                 // startup dir; NULL = start in current
        &si,                                                  // pointer to startup info (input)
        &pi ) )                                               // pointer to process info (output)
    {
        ::CloseHandle( hReadPipe );
        ::CloseHandle( hWritePipe );
        return -1;
    }

    // close the write end of the pipe so the child will terminate it with EOF
    ::CloseHandle( hWritePipe );

    // read from the pipe until EOF condition reached
    tchar_t buffer[80];
    unsigned long count;
    tstringstream stream;
    BOOL success = TRUE;
    do
    {
        while ( success = ReadFile( hReadPipe, buffer, sizeof(buffer), &count, NULL ) )
        {
            if( success )
            {
                stream.write( buffer, count );
            }
            else
            {
                if ( ::GetLastError() == ERROR_BROKEN_PIPE )
                {
                    break;
                }
                else
                {
                    return -1;
                }
            }
        }
    } while( success && count );

    // done reading, close our read pipe
    ::CloseHandle( hReadPipe );

    // copy output string
    output = stream.str();

    // get exit code
    DWORD result = 0;
    BOOL codeResult = ::GetExitCodeProcess( pi.hProcess, &result );
    HELIUM_ASSERT( codeResult );

    // close the process handle
    ::CloseHandle( pi.hProcess );
    ::CloseHandle( pi.hThread );

    return result;
}
Exemplo n.º 3
0
/// Compute the corners of this view frustum, outputting the result in separate arrays for each component.
///
/// A view frustum can have either four or eight corners depending on whether a far clip plane exists (eight
/// corners) or whether an infinite far clip plane is used (four corners).
///
/// Note that this assumes that the frustum is always properly defined, with each possible combination of
/// neighboring clip planes intersecting at a valid point.
///
/// @param[out] pCornersX  SIMD-aligned array in which the frustum corner x coordinates will be stored.  This must
///                        point to a region of memory large enough for four points if this frustum has an infinite
///                        far clip plane, or eight points if this frustum has a normal far clip plane.
/// @param[out] pCornersY  SIMD-aligned array in which the frustum corner y coordinates will be stored.  This must
///                        point to a region of memory large enough for four points if this frustum has an infinite
///                        far clip plane, or eight points if this frustum has a normal far clip plane.
/// @param[out] pCornersZ  SIMD-aligned array in which the frustum corner z coordinates will be stored.  This must
///                        point to a region of memory large enough for four points if this frustum has an infinite
///                        far clip plane, or eight points if this frustum has a normal far clip plane.
///
/// @return  Number of clip planes computed (either four or eight).
size_t Helium::Simd::Frustum::ComputeCornersSoa( float32_t* pCornersX, float32_t* pCornersY, float32_t* pCornersZ ) const
{
    HELIUM_ASSERT( pCornersX );
    HELIUM_ASSERT( pCornersY );
    HELIUM_ASSERT( pCornersZ );

    // Load the plane combinations used to compute the four corners on the near clip plane.
    Helium::Simd::Register plane0A = Helium::Simd::LoadAligned( m_planeA );
    Helium::Simd::Register plane0B = Helium::Simd::LoadAligned( m_planeB );
    Helium::Simd::Register plane0C = Helium::Simd::LoadAligned( m_planeC );
    Helium::Simd::Register plane0D = Helium::Simd::LoadAligned( m_planeD );

    Helium::Simd::Register plane1A = _mm_shuffle_ps( plane0A, plane0A, _MM_SHUFFLE( 0, 1, 3, 2 ) );
    Helium::Simd::Register plane1B = _mm_shuffle_ps( plane0B, plane0B, _MM_SHUFFLE( 0, 1, 3, 2 ) );
    Helium::Simd::Register plane1C = _mm_shuffle_ps( plane0C, plane0C, _MM_SHUFFLE( 0, 1, 3, 2 ) );
    Helium::Simd::Register plane1D = _mm_shuffle_ps( plane0D, plane0D, _MM_SHUFFLE( 0, 1, 3, 2 ) );

    Helium::Simd::Register plane2A = Helium::Simd::LoadSplat32( m_planeA + PLANE_NEAR );
    Helium::Simd::Register plane2B = Helium::Simd::LoadSplat32( m_planeB + PLANE_NEAR );
    Helium::Simd::Register plane2C = Helium::Simd::LoadSplat32( m_planeC + PLANE_NEAR );
    Helium::Simd::Register plane2D = Helium::Simd::LoadSplat32( m_planeD + PLANE_NEAR );

    // Compute all four near clip corners.
    Helium::Simd::Register detAB = _mm_sub_ps( _mm_mul_ps( plane0A, plane1B ), _mm_mul_ps( plane0B, plane1A ) );
    Helium::Simd::Register detAC = _mm_sub_ps( _mm_mul_ps( plane0A, plane1C ), _mm_mul_ps( plane0C, plane1A ) );
    Helium::Simd::Register detBC = _mm_sub_ps( _mm_mul_ps( plane0B, plane1C ), _mm_mul_ps( plane0C, plane1B ) );

    Helium::Simd::Register detAD = _mm_sub_ps( _mm_mul_ps( plane0A, plane1D ), _mm_mul_ps( plane0D, plane1A ) );
    Helium::Simd::Register detBD = _mm_sub_ps( _mm_mul_ps( plane0B, plane1D ), _mm_mul_ps( plane0D, plane1B ) );
    Helium::Simd::Register detDC = _mm_sub_ps( _mm_mul_ps( plane0D, plane1C ), _mm_mul_ps( plane0C, plane1D ) );

    // XXX: Denominator sign is flipped here to handle the fact our plane D component is the negative distance from
    // the origin (sign gets flipped when placed at the opposite side of the linear equation set for each plane when
    // solving).
    //
    // Our plane equation:
    //     Ax + By + Cz + D = 0
    ///
    // ...in the form needed for solving using Cramer's rule:
    //     Ax + By + Cz = -D
    Helium::Simd::Register denominator = _mm_rcp_ps(
        _mm_sub_ps(
            _mm_mul_ps( plane2B, detAC ),
            _mm_add_ps(
                _mm_mul_ps( plane2A, detBC ),
                _mm_mul_ps( plane2C, detAB ) ) ) );

    //Helium::Simd::Register cornerXVec = _mm_mul_ps(
    //    _mm_add_ps(
    //        _mm_sub_ps(
    //            _mm_mul_ps( plane2D, detBC ),
    //            _mm_mul_ps( plane2B, detDC ) ),
    //        _mm_mul_ps( plane2C, detDB ) ),
    //    denominator );
    Helium::Simd::Register cornerXVec = _mm_mul_ps(
        _mm_sub_ps(  // Note that we subtract...
            _mm_sub_ps(
                _mm_mul_ps( plane2D, detBC ),
                _mm_mul_ps( plane2B, detDC ) ),
            _mm_mul_ps( plane2C, detBD ) ),  // ...because the 2x2 sub-matrix components are switched here.
        denominator );

    Helium::Simd::Register cornerYVec = _mm_mul_ps(
        _mm_add_ps(
            _mm_sub_ps(
                _mm_mul_ps( plane2A, detDC ),
                _mm_mul_ps( plane2D, detAC ) ),
            _mm_mul_ps( plane2C, detAD ) ),
        denominator );

    Helium::Simd::Register cornerZVec = _mm_mul_ps(
        _mm_add_ps(
            _mm_sub_ps(
                _mm_mul_ps( plane2A, detBD ),
                _mm_mul_ps( plane2B, detAD ) ),
            _mm_mul_ps( plane2D, detAB ) ),
        denominator );

    Helium::Simd::StoreAligned( pCornersX, cornerXVec );
    Helium::Simd::StoreAligned( pCornersY, cornerYVec );
    Helium::Simd::StoreAligned( pCornersZ, cornerZVec );

    // If this frustum has an infinite far clip plane, we are done.
    if( m_bInfiniteFarClip )
    {
        return 4;
    }

    // Compute the far clip plane corners, reusing data from the near clip plane corner calculations where possible.
    plane2A = Helium::Simd::LoadSplat32( m_planeA + PLANE_FAR );
    plane2B = Helium::Simd::LoadSplat32( m_planeB + PLANE_FAR );
    plane2C = Helium::Simd::LoadSplat32( m_planeC + PLANE_FAR );
    plane2D = Helium::Simd::LoadSplat32( m_planeD + PLANE_FAR );

    denominator = _mm_rcp_ps(
        _mm_sub_ps(
            _mm_mul_ps( plane2B, detAC ),
            _mm_add_ps(
                _mm_mul_ps( plane2A, detBC ),
                _mm_mul_ps( plane2C, detAB ) ) ) );

    //cornerXVec = _mm_mul_ps(
    //    _mm_add_ps(
    //        _mm_sub_ps(
    //            _mm_mul_ps( plane2D, detBC ),
    //            _mm_mul_ps( plane2B, detDC ) ),
    //        _mm_mul_ps( plane2C, detDB ) ),
    //    denominator );
    cornerXVec = _mm_mul_ps(
        _mm_sub_ps(  // Note that we subtract...
            _mm_sub_ps(
                _mm_mul_ps( plane2D, detBC ),
                _mm_mul_ps( plane2B, detDC ) ),
            _mm_mul_ps( plane2C, detBD ) ),  // ...because the 2x2 sub-matrix components are switched here.
        denominator );

    cornerYVec = _mm_mul_ps(
        _mm_add_ps(
            _mm_sub_ps(
                _mm_mul_ps( plane2A, detDC ),
                _mm_mul_ps( plane2D, detAC ) ),
            _mm_mul_ps( plane2C, detAD ) ),
        denominator );

    cornerZVec = _mm_mul_ps(
        _mm_add_ps(
            _mm_sub_ps(
                _mm_mul_ps( plane2A, detBD ),
                _mm_mul_ps( plane2B, detAD ) ),
            _mm_mul_ps( plane2D, detAB ) ),
        denominator );

    Helium::Simd::StoreAligned( pCornersX + 4, cornerXVec );
    Helium::Simd::StoreAligned( pCornersY + 4, cornerYVec );
    Helium::Simd::StoreAligned( pCornersZ + 4, cornerZVec );

    return 8;
}