/// @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; }
/// @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 ); }
/// 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; }
/// @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; }