/// @copydoc ObjectLoaderInitialization::Initialize()
GameObjectLoader* ObjectLoaderInitializationWin::Initialize()
{
#if HELIUM_TOOLS
    if( !EditorObjectLoader::InitializeStaticInstance() )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "ObjectLoaderFactoryWin::Create(): Failed to initialize EditorObjectLoader instance.\n" ) );

        return NULL;
    }

    ObjectPreprocessor* pObjectPreprocessor = ObjectPreprocessor::CreateStaticInstance();
    HELIUM_ASSERT( pObjectPreprocessor );
    PlatformPreprocessor* pPlatformPreprocessor = new PcPreprocessor;
    HELIUM_ASSERT( pPlatformPreprocessor );
    pObjectPreprocessor->SetPlatformPreprocessor( Cache::PLATFORM_PC, pPlatformPreprocessor );
#else
    if( !PcCacheObjectLoader::InitializeStaticInstance() )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "ObjectLoaderFactoryWin::Create() Failed to initialize PcCacheObjectLoader instance.\n" ) );

        return NULL;
    }
#endif

    GameObjectLoader* pObjectLoader = GameObjectLoader::GetStaticInstance();
    HELIUM_ASSERT( pObjectLoader );

    return pObjectLoader;
}
예제 #2
0
/// @copydoc GameObjectLoader::OnPrecacheReady()
void EditorObjectLoader::OnPrecacheReady( GameObject* pObject, PackageLoader* pPackageLoader )
{
    HELIUM_ASSERT( pObject );
    HELIUM_ASSERT( pPackageLoader );

    // The default template object for a given type never has its resource data preprocessed, so there's no need to
    // precache default template objects.
    if( pObject->IsDefaultTemplate() )
    {
        return;
    }

    // Retrieve the object preprocessor if it exists.
    ObjectPreprocessor* pObjectPreprocessor = ObjectPreprocessor::GetStaticInstance();
    if( !pObjectPreprocessor )
    {
        HELIUM_TRACE(
            TRACE_WARNING,
            ( TXT( "EditorObjectLoader::OnPrecacheReady(): Missing ObjectPreprocessor to use for resource " )
            TXT( "preprocessing.\n" ) ) );

        return;
    }

    // We only need to do precache handling for resources, so skip non-resource types.
    Resource* pResource = Reflect::SafeCast< Resource >( pObject );
    if( !pResource )
    {
        return;
    }

    // Grab the package timestamp.
    HELIUM_ASSERT( pPackageLoader->IsSourcePackageFile() );
    int64_t objectTimestamp = pPackageLoader->GetFileTimestamp();

    // Attempt to load the resource data.
    pObjectPreprocessor->LoadResourceData( pResource, objectTimestamp );
}
예제 #3
0
/// Begin asynchronous loading of a shader variant.
///
/// @param[in] pShader          Parent shader resource.
/// @param[in] shaderType       Shader type.
/// @param[in] userOptionIndex  Index associated with the user option combination for the shader variant.
///
/// @return  ID associated with the load procedure, or an invalid index if the load could not be started.
///
/// @see TryFinishLoadVariant()
size_t ShaderVariantResourceHandler::BeginLoadVariant(
    Shader* pShader,
    RShader::EType shaderType,
    uint32_t userOptionIndex )
{
    HELIUM_ASSERT( pShader );
    HELIUM_ASSERT( static_cast< size_t >( shaderType ) < static_cast< size_t >( RShader::TYPE_MAX ) );

    // Attempt to locate an existing load request for the specified shader variant.
    LoadRequest* pLoadRequest = m_loadRequestPool.Allocate();
    HELIUM_ASSERT( pLoadRequest );
    pLoadRequest->shaderType = shaderType;
    pLoadRequest->userOptionIndex = userOptionIndex;
    HELIUM_ASSERT( !pLoadRequest->spVariant );
    pLoadRequest->requestCount = 1;

    LoadRequestSetType::ConstAccessor loadRequestConstAccessor;
    if( !m_loadRequestSet.Insert( loadRequestConstAccessor, pLoadRequest ) )
    {
        // Request exists, so increment its reference count.
        m_loadRequestPool.Release( pLoadRequest );

        pLoadRequest = *loadRequestConstAccessor;
        HELIUM_ASSERT( pLoadRequest );

        AtomicIncrementAcquire( pLoadRequest->requestCount );

        size_t loadId = m_loadRequestPool.GetIndex( pLoadRequest );
        HELIUM_ASSERT( IsValid( loadId ) );

        return loadId;
    }

    // Adding a new request, so create the variant object if it does not yet exist.
    tchar_t shaderTypeCharacter;
    if( shaderType == RShader::TYPE_VERTEX )
    {
        shaderTypeCharacter = TXT( 'v' );
    }
    else
    {
        HELIUM_ASSERT( shaderType == RShader::TYPE_PIXEL );
        shaderTypeCharacter = TXT( 'p' );
    }

    String variantNameString;
    variantNameString.Format( TXT( "%c%" ) TPRIu32, shaderTypeCharacter, userOptionIndex );

    Name variantName( variantNameString );
    variantNameString.Clear();

    pLoadRequest->spVariant.Set( Reflect::AssertCast< ShaderVariant >( pShader->FindChild( variantName ) ) );
    if( !pLoadRequest->spVariant )
    {
        if( !GameObject::Create< ShaderVariant >( pLoadRequest->spVariant, variantName, pShader ) )
        {
            HELIUM_TRACE(
                TRACE_ERROR,
                ( TXT( "ShaderVariantResourceHandler::BeginLoadVariant(): Failed to create shader variant object " )
                  TXT( "\"%s:%s\".\n" ) ),
                *pShader->GetPath().ToString(),
                *variantName );
        }
        else
        {
            HELIUM_ASSERT( pLoadRequest->spVariant );
        }
    }

    // If we have an object for the shader variant, attempt to load its resource data.
    ShaderVariant* pVariant = pLoadRequest->spVariant;
    if( pVariant && !pVariant->GetAnyFlagSet( GameObject::FLAG_PRECACHED ) )
    {
        GameObject* pPackageObject;
        for( pPackageObject = pShader->GetOwner();
                pPackageObject != NULL && !pPackageObject->IsPackage();
                pPackageObject = pPackageObject->GetOwner() )
        {
            // This space intentionally left blank...
        }

        HELIUM_ASSERT( pPackageObject );

        PackageLoader* pPackageLoader = Reflect::AssertCast< Package >( pPackageObject )->GetLoader();
        HELIUM_ASSERT( pPackageLoader );
        HELIUM_ASSERT( pPackageLoader->IsSourcePackageFile() );

        ObjectPreprocessor* pObjectPreprocessor = ObjectPreprocessor::GetStaticInstance();
        HELIUM_ASSERT( pObjectPreprocessor );

        pObjectPreprocessor->LoadResourceData( pVariant, pPackageLoader->GetFileTimestamp() );

        // Resource data loaded, so deserialize the persistent data for the current platform and begin precaching.
        CacheManager& rCacheManager = CacheManager::GetStaticInstance();
        const Resource::PreprocessedData& rPreprocessedData = pVariant->GetPreprocessedData(
                    rCacheManager.GetCurrentPlatform() );
        const DynArray< uint8_t >& rPersistentDataBuffer = rPreprocessedData.persistentDataBuffer;

        //PMDTODO: Implmenet this
//         BinaryDeserializer deserializer;
//         deserializer.Prepare( rPersistentDataBuffer.GetData(), rPersistentDataBuffer.GetSize() );
//         deserializer.BeginSerialize();
//         pVariant->SerializePersistentResourceData( deserializer );
//         deserializer.EndSerialize();
        Reflect::ObjectPtr persistent_resource_data = Cache::ReadCacheObjectFromBuffer(rPersistentDataBuffer);
        pVariant->LoadPersistentResourceObject(persistent_resource_data);
        pVariant->BeginPrecacheResourceData();
    }

    size_t loadId = m_loadRequestPool.GetIndex( pLoadRequest );
    HELIUM_ASSERT( IsValid( loadId ) );

    return loadId;
}
예제 #4
0
/// @copydoc GameObjectLoader::CacheObject()
bool EditorObjectLoader::CacheObject( GameObject* pObject, bool bEvictPlatformPreprocessedResourceData )
{
    HELIUM_ASSERT( pObject );

    // Don't cache broken objects or packages.
    if( pObject->GetAnyFlagSet( GameObject::FLAG_BROKEN ) || pObject->IsPackage() )
    {
        return false;
    }

    // Make sure we have an object preprocessor instance with which to cache the object.
    ObjectPreprocessor* pObjectPreprocessor = ObjectPreprocessor::GetStaticInstance();
    if( !pObjectPreprocessor )
    {
        HELIUM_TRACE(
            TRACE_WARNING,
            TXT( "EditorObjectLoader::CacheObject(): Missing ObjectPreprocessor to use for caching.\n" ) );

        return false;
    }

    // Configuration objects should not be cached.
    GameObjectPath objectPath = pObject->GetPath();

    Config& rConfig = Config::GetStaticInstance();
    GameObjectPath configPackagePath = rConfig.GetConfigContainerPackagePath();
    HELIUM_ASSERT( !configPackagePath.IsEmpty() );

    for( GameObjectPath testPath = objectPath; !testPath.IsEmpty(); testPath = testPath.GetParent() )
    {
        if( testPath == configPackagePath )
        {
            return false;
        }
    }

    // Get the timestamp for the object based on the timestamp of its source package file and, if it's a resource,
    // the timestamp of the source resource file.
    GameObject* pPackageObject;
    for( pPackageObject = pObject;
        pPackageObject && !pPackageObject->IsPackage();
        pPackageObject = pPackageObject->GetOwner() )
    {
    }

    HELIUM_ASSERT( pPackageObject );

    PackageLoader* pPackageLoader = Reflect::AssertCast< Package >( pPackageObject )->GetLoader();
    HELIUM_ASSERT( pPackageLoader );
    HELIUM_ASSERT( pPackageLoader->IsSourcePackageFile() );

    int64_t objectTimestamp = pPackageLoader->GetFileTimestamp();

    if( !pObject->IsDefaultTemplate() )
    {
        Resource* pResource = Reflect::SafeCast< Resource >( pObject );
        if( pResource )
        {
            GameObjectPath baseResourcePath = pResource->GetPath();
            HELIUM_ASSERT( !baseResourcePath.IsPackage() );
            for( ; ; )
            {
                GameObjectPath parentPath = baseResourcePath.GetParent();
                if( parentPath.IsEmpty() || parentPath.IsPackage() )
                {
                    break;
                }

                baseResourcePath = parentPath;
            }

            Path sourceFilePath;
            if ( !File::GetDataDirectory( sourceFilePath ) )
            {
                HELIUM_TRACE(
                    TRACE_WARNING,
                    TXT( "EditorObjectLoader::CacheObject(): Could not obtain data directory.\n" ) );

                return false;
            }

            sourceFilePath += baseResourcePath.ToFilePathString().GetData();

            int64_t sourceFileTimestamp = sourceFilePath.ModifiedTime();
            if( sourceFileTimestamp > objectTimestamp )
            {
                objectTimestamp = sourceFileTimestamp;
            }
        }
    }

    // Cache the object.
    bool bSuccess = pObjectPreprocessor->CacheObject(
        pObject,
        objectTimestamp,
        bEvictPlatformPreprocessedResourceData );
    if( !bSuccess )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "EditorObjectLoader: Failed to cache object \"%s\".\n" ),
            *objectPath.ToString() );
    }

    return bSuccess;
}