예제 #1
0
/// Initialize this cache.
///
/// This will verify the existence of the given files and prepare for cache loading.  Note that no file loading is
/// performed at this time.
///
/// Once initialization is performed, the table of contents must be loaded using BeginLoadToc().
///
/// @param[in] name            Name identifying this cache.
/// @param[in] platform        Cache platform identifier.
/// @param[in] pTocFileName    Path name of the table of contents file.
/// @param[in] pCacheFileName  Path name of the cache file.
///
/// @return  True if initialization was successful, false if not.
///
/// @see Shutdown(), BeginLoadToc()
bool Cache::Initialize( Name name, EPlatform platform, const tchar_t* pTocFileName, const tchar_t* pCacheFileName )
{
    HELIUM_ASSERT( !name.IsEmpty() );
    HELIUM_ASSERT( static_cast< size_t >( platform ) < static_cast< size_t >( PLATFORM_MAX ) );
    HELIUM_ASSERT( pTocFileName );
    HELIUM_ASSERT( pCacheFileName );

    Shutdown();

    m_name = name;
    m_platform = platform;

    Path tocFile( pTocFileName );
    int64_t tocSize64 = tocFile.Size();
    if( tocSize64 != -1 && static_cast< uint64_t >( tocSize64 ) >= UINT32_MAX )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "Cache::Initialize(): TOC file \"%s\" exceeds the maximum allowed size for TOC files (2 GB).\n" ),
            pTocFileName );

        return false;
    }

    m_tocFileName = pTocFileName;
    m_cacheFileName = pCacheFileName;

    m_tocSize = static_cast< uint32_t >( tocSize64 );

    HELIUM_ASSERT( !m_pEntryPool );
    m_pEntryPool = new ObjectPool< Entry >( ENTRY_POOL_BLOCK_SIZE );
    HELIUM_ASSERT( m_pEntryPool );

    return true;
}
예제 #2
0
bool Helium::AssetResolver::Resolve( const Name& identity, Reflect::ObjectPtr& pointer, const Reflect::MetaClass* pointerClass )
{
	// Paths begin with /
	if (!identity.IsEmpty() && (*identity)[0] == '/')
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Resolving object [%s]\n" ), identity.Get() );

		AssetPath p;
		p.Set(*identity);

		size_t loadRequestId = AssetLoader::GetStaticInstance()->BeginLoadObject(p);
		m_Fixups.Push( Fixup( pointer, pointerClass, loadRequestId ) );

		return true;
	}
	else
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Deferring resolution of [%s] to archive\n" ), identity.Get() );
	}

	return false;
}
예제 #3
0
/// Initialize this package loader for loading from the specified cache files.
///
/// @param[in] cacheName  Name of the cache to use.
///
/// @return  True if initialization was successful, false if not.
///
/// @see Shutdown()
bool CachePackageLoader::Initialize( Name cacheName )
{
    HELIUM_ASSERT( !cacheName.IsEmpty() );

    Shutdown();

    // Acquire the cache.
    CacheManager& rCacheManager = CacheManager::GetStaticInstance();

    m_pCache = rCacheManager.GetCache( cacheName );
    if( !m_pCache )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "CachePackageLoader::Initialize(): Failed to initialize cache \"%s\".\n" ),
            *cacheName );

        return false;
    }

    return true;
}
예제 #4
0
/// Resolve a dependency on a type reference.
///
/// @param[in] typeName  Type name.
///
/// @return  Dependency index.
///
/// @see ResolveObjectDependency()
uint32_t BinarySerializer::ResolveTypeDependency( Name typeName )
{
    uint32_t typeIndex;
    SetInvalid( typeIndex );

    if( !typeName.IsEmpty() )
    {
        size_t dependencyCount = m_typeDependencies.GetSize();
        for( size_t dependencyIndex = 0; dependencyIndex < dependencyCount; ++dependencyIndex )
        {
            if( m_typeDependencies[ dependencyIndex ] == typeName )
            {
                return static_cast< uint32_t >( dependencyIndex );
            }
        }

        HELIUM_ASSERT( dependencyCount < UINT32_MAX );
        m_typeDependencies.Push( typeName );
        typeIndex = static_cast< uint32_t >( dependencyCount );
    }

    return typeIndex;
}
예제 #5
0
bool Helium::AssetResolver::Resolve( const Name& identity, Reflect::ObjectPtr& pointer, const Reflect::MetaClass* pointerClass )
{
	// Paths begin with /
	if (!identity.IsEmpty() && (*identity)[0] == '/')
	{
		HELIUM_TRACE( TraceLevels::Info, TXT( "Resolving object [%s]\n" ), identity.Get() );

		AssetPath p;
		p.Set(*identity);

		size_t loadRequestId = AssetLoader::GetStaticInstance()->BeginLoadObject(p);
		m_Fixups.Push( Fixup( pointer, pointerClass, loadRequestId ) );

		return true;
	}
	else
	{
#if HELIUM_TOOLS
		// Some extra checking to make friendly error messages
		String str ( identity.Get() );
		uint32_t index = Invalid< uint32_t >();
		int parseSuccessful = str.Parse( "%d", &index );

		if (!parseSuccessful)
		{
			HELIUM_TRACE(
				TraceLevels::Warning,
				"AssetResolver::Resolve - Identity '%s' is not a number, but doesn't start with '/'. If this is a path, it must begin with '/'!\n", 
				*str);
		}
#endif

		HELIUM_TRACE( TraceLevels::Debug, TXT( "Deferring resolution of [%s] to archive\n" ), identity.Get() );
	}

	return false;
}
예제 #6
0
/// Modify the name, owner, or instance index of this object.
///
/// @param[in] rParameters  Object rename parameters.
///
/// @return  True if this object was renamed successfully, false if not.
///
/// @see GetName(), GetOwner(), GetInstanceIndex()
bool GameObject::Rename( const RenameParameters& rParameters )
{
    Name name = rParameters.name;
    GameObject* pOwner = rParameters.spOwner;
    uint32_t instanceIndex = rParameters.instanceIndex;

    HELIUM_TRACE(
        TraceLevels::Debug,
        TXT("GameObject::Rename(): Renaming object \"%s\" to \"%s\" (Old Owner: \"%s\". New Owner: \"%s\".)\n"),
        *m_name,
        *rParameters.name,
        m_spOwner.ReferencesObject() ? *m_spOwner->GetPath().ToString() : TXT("[none]"),
        rParameters.spOwner.ReferencesObject() ? *rParameters.spOwner->GetPath().ToString() : TXT("[none]"));

    // Only allow setting an empty name if no owner or instance index are given and this object has no children.
    if( name.IsEmpty() )
    {
        HELIUM_ASSERT( !pOwner );
        HELIUM_ASSERT( IsInvalid( instanceIndex ) );
        if( pOwner || IsValid( instanceIndex ) )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                ( TXT( "GameObject::Rename(): Objects cannot have name information cleared if being assigned an " )
                  TXT( "owner or instance index.\n" ) ) );

            return false;
        }

        HELIUM_ASSERT( !m_wpFirstChild );
        if( m_wpFirstChild )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "GameObject::Rename(): Cannot clear name information for objects with children.\n" ) );

            return false;
        }
    }

    // Don't allow setting the owner to ourself.
    if( pOwner == this )
    {
        HELIUM_TRACE( TraceLevels::Error, TXT( "GameObject::Rename(): Cannot set the owner of an object to itself.\n" ) );

        return false;
    }

    // Don't allow setting the owner to an object with no name information.
    if( pOwner && pOwner->m_name.IsEmpty() )
    {
        HELIUM_TRACE(
            TraceLevels::Error,
            TXT( "GameObject::Rename(): Cannot set the owner of an object to an object with no path information.\n" ) );

        return false;
    }

    if( IsPackage() )
    {
        // Don't allow package objects to be children of non-package objects.
        if( pOwner && !pOwner->IsPackage() )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "GameObject::Rename(): Cannot set a non-package as the owner of a package.\n" ) );

            return false;
        }

        // Don't allow instance indexing for packages.
        if( IsValid( instanceIndex ) )
        {
            HELIUM_TRACE(
                TraceLevels::Error,
                TXT( "GameObject::Rename(): Instance indexing not supported for packages.\n" ) );

            return false;
        }
    }

    // Don't need to do anything if the name, owner, and instance index are not changing.
    if( name == m_name &&
        pOwner == m_spOwner &&
        ( instanceIndex == m_instanceIndex || ( instanceIndex == INSTANCE_INDEX_AUTO && IsValid( m_instanceIndex ) ) ) )
    {
        return true;
    }

    // Hold onto a reference to the current owner until we return from this function.  This is done in case this object
    // has the last strong reference to it, in which case we would encounter a deadlock if clearing its reference while
    // we still have a write lock on the object list (object destruction also requires acquiring a write lock).
    GameObjectPtr spOldOwner = m_spOwner;

    {
        // Acquire a write lock on the object list to prevent objects from being added and removed as well as keep
        // objects from being renamed while this object is being renamed.
        ScopeWriteLock scopeLock( sm_objectListLock );

        // Get the list of children belonging to the new owner.
        GameObjectWPtr& rwpOwnerFirstChild = ( pOwner ? pOwner->m_wpFirstChild : sm_wpFirstTopLevelObject );

        // Don't check for name clashes if we're clearing the object path name information.
        if( !name.IsEmpty() )
        {
            // Resolve name clashes either through the instance index lookup map (if an instance index will be assigned)
            // or through a child object search (if no instance index will be used).
            if( IsValid( instanceIndex ) )
            {
                // Get the instance index map for the requested object name.
                ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap();
                HELIUM_ASSERT( sm_pEmptyNameInstanceIndexMap );
                HELIUM_ASSERT( sm_pEmptyInstanceIndexSet );

                sm_pEmptyNameInstanceIndexMap->First() = ( pOwner ? pOwner->GetPath() : GameObjectPath( NULL_NAME ) );
                sm_pEmptyInstanceIndexSet->First() = name;

                ChildNameInstanceIndexMap::Accessor childNameMapAccessor;
                rNameInstanceIndexMap.Insert( childNameMapAccessor, *sm_pEmptyNameInstanceIndexMap );

                NameInstanceIndexMap::Accessor indexSetAccessor;
                childNameMapAccessor->Second().Insert( indexSetAccessor, *sm_pEmptyInstanceIndexSet );

                InstanceIndexSet& rIndexSet = indexSetAccessor->Second();
                InstanceIndexSet::ConstAccessor indexAccessor;

                if( instanceIndex == INSTANCE_INDEX_AUTO )
                {
                    // Pick an unused instance index.
                    instanceIndex = 0;
                    while( !rIndexSet.Insert( indexAccessor, instanceIndex ) )
                    {
                        ++instanceIndex;
                        HELIUM_ASSERT( instanceIndex < INSTANCE_INDEX_AUTO );
                    }
                }
                else
                {
                    // Attempt to acquire the specified instance index.
                    if( !rIndexSet.Insert( indexAccessor, instanceIndex ) )
                    {
                        HELIUM_TRACE(
                            TraceLevels::Error,
                            ( TXT( "GameObject::Rename(): Object already exists with the specified owner (%s), name " )
                              TXT( "(%s), and instance index (%" ) TPRIu32 TXT( ").\n" ) ),
                            ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ),
                            *name,
                            instanceIndex );

                        return false;
                    }
                }
            }
            else
            {
                // Check each child of the new owner for a name clash.
                for( GameObject* pChild = rwpOwnerFirstChild; pChild != NULL; pChild = pChild->m_wpNextSibling )
                {
                    if( pChild->m_name == name && pChild->m_instanceIndex == instanceIndex )
                    {
                        HELIUM_TRACE(
                            TraceLevels::Error,
                            ( TXT( "GameObject::Rename(): Object already exists with the specified owner (%s) and " )
                              TXT( "name (%s).\n" ) ),
                            ( pOwner ? *pOwner->GetPath().ToString() : TXT( "none" ) ),
                            *name );

                        return false;
                    }
                }
            }
        }

        // Remove any old instance index tracking for the old path name.
        if( IsValid( m_instanceIndex ) )
        {
            GameObjectPath ownerPath = ( spOldOwner ? spOldOwner->GetPath() : GameObjectPath( NULL_NAME ) );

            ChildNameInstanceIndexMap& rNameInstanceIndexMap = GetNameInstanceIndexMap();

            ChildNameInstanceIndexMap::Accessor childMapAccessor;
            HELIUM_VERIFY( rNameInstanceIndexMap.Find( childMapAccessor, ownerPath ) );

            NameInstanceIndexMap& rNameMap = childMapAccessor->Second();
            NameInstanceIndexMap::Accessor nameMapAccessor;
            HELIUM_VERIFY( rNameMap.Find( nameMapAccessor, m_name ) );

            InstanceIndexSet& rIndexSet = nameMapAccessor->Second();
            HELIUM_VERIFY( rIndexSet.Remove( m_instanceIndex ) );

            /*
            if( rIndexSet.IsEmpty() )
            {
                HELIUM_VERIFY( rNameMap.Remove( nameMapAccessor ) );
                if( rNameMap.IsEmpty() )
                {
                    HELIUM_VERIFY( rNameInstanceIndexMap.Remove( childMapAccessor ) );
                }
            }
            */
        }

        // If the owner of this object is changing, remove this object from its old owner's list and add it to the new
        // owner.
        if( spOldOwner.Get() != pOwner || ( m_name.IsEmpty() ? !name.IsEmpty() : name.IsEmpty() ) )
        {
            // Object should not be in any child object lists if its name is empty.
            if( !m_name.IsEmpty() )
            {
                GameObjectWPtr& rwpOldOwnerFirstChild =
                    ( spOldOwner ? spOldOwner->m_wpFirstChild : sm_wpFirstTopLevelObject );

                GameObject* pPreviousChild = NULL;
                GameObject* pChild = rwpOldOwnerFirstChild;
                while( pChild )
                {
                    if( pChild == this )
                    {
                        ( pPreviousChild ? pPreviousChild->m_wpNextSibling : rwpOldOwnerFirstChild ) = m_wpNextSibling;
                        m_wpNextSibling.Release();

                        break;
                    }

                    pPreviousChild = pChild;
                    pChild = pChild->m_wpNextSibling;
                }
            }

            HELIUM_ASSERT( !m_wpNextSibling );

            // Only store the object in a child object list if it is being given a valid name.
            if( !name.IsEmpty() )
            {
                m_wpNextSibling = rwpOwnerFirstChild;
                rwpOwnerFirstChild = this;
            }
        }

        // Set the new path name.
        m_name = name;
        m_spOwner = pOwner;
        m_instanceIndex = instanceIndex;

        // Update path information for this object and its children.
        UpdatePath();
    }

    return true;
}
예제 #7
0
파일: Shader.cpp 프로젝트: euler0/Helium
/// Get a unique index associated with a specific set of shader preprocessor options.
///
/// Note that this will always attempt to match up a valid index, even if invalid options are specified or select
/// options are missing.
///
/// @param[in] shaderType       Type of shader.
/// @param[in] pOptionPairs     Mixed list of shader toggle states and shader selection pair values.
/// @param[in] optionPairCount  Number of options in the option pair array.
///
/// @return  Index to use for the specified options.
size_t Shader::Options::GetOptionSetIndex(
    RShader::EType shaderType,
    const SelectPair* pOptionPairs,
    size_t optionPairCount ) const
{
    HELIUM_ASSERT( static_cast< size_t >( shaderType ) < static_cast< size_t >( RShader::TYPE_MAX ) );
    HELIUM_ASSERT( pOptionPairs || optionPairCount == 0 );

    uint32_t shaderTypeMask = ( 1 << shaderType );

    size_t optionIndex = 0;
    size_t optionIndexMultiplier = 1;

    static const Name disabledToggleValues[] = { Name( NULL_NAME ), Name( TXT( "0" ) ), Name( TXT( "false" ) ) };

    size_t shaderToggleCount = m_toggles.GetSize();
    for( size_t shaderToggleIndex = 0; shaderToggleIndex < shaderToggleCount; ++shaderToggleIndex )
    {
        const Toggle& rShaderToggle = m_toggles[ shaderToggleIndex ];
        if( !( rShaderToggle.shaderTypeFlags & shaderTypeMask ) )
        {
            continue;
        }

        Name shaderToggleName = rShaderToggle.name;

        for( size_t optionPairIndex = 0; optionPairIndex < optionPairCount; ++optionPairIndex )
        {
            const SelectPair& rOptionPair = pOptionPairs[ optionPairIndex ];
            if( rOptionPair.name == shaderToggleName )
            {
                Name value = rOptionPair.choice;

                size_t disabledValueIndex;
                for( disabledValueIndex = 0;
                    disabledValueIndex < HELIUM_ARRAY_COUNT( disabledToggleValues );
                    ++disabledValueIndex )
                {
                    if( value == disabledToggleValues[ disabledValueIndex ] )
                    {
                        break;
                    }
                }

                if( disabledValueIndex >= HELIUM_ARRAY_COUNT( disabledToggleValues ) )
                {
                    optionIndex |= optionIndexMultiplier;
                }

                break;
            }
        }

        optionIndexMultiplier <<= 1;
    }

    size_t shaderSelectCount = m_selects.GetSize();
    for( size_t shaderSelectIndex = 0; shaderSelectIndex < shaderSelectCount; ++shaderSelectIndex )
    {
        const Select& rShaderSelect = m_selects[ shaderSelectIndex ];
        if( !( rShaderSelect.shaderTypeFlags & shaderTypeMask ) )
        {
            continue;
        }

        Name shaderSelectName = rShaderSelect.name;

        bool bSetSelectIndex = false;
        for( size_t optionPairIndex = 0; optionPairIndex < optionPairCount; ++optionPairIndex )
        {
            const SelectPair& rPair = pOptionPairs[ optionPairIndex ];
            if( rPair.name == shaderSelectName )
            {
                const DynArray< Name >& rShaderSelectChoices = rShaderSelect.choices;
                size_t shaderSelectChoiceCount = rShaderSelectChoices.GetSize();

                Name targetChoiceName = rPair.choice;
                if( !targetChoiceName.IsEmpty() )
                {
                    for( size_t shaderSelectChoiceIndex = 0;
                        shaderSelectChoiceIndex < shaderSelectChoiceCount;
                        ++shaderSelectChoiceIndex )
                    {
                        if( rShaderSelectChoices[ shaderSelectChoiceIndex ] == targetChoiceName )
                        {
                            optionIndex += shaderSelectChoiceIndex * optionIndexMultiplier;
                            bSetSelectIndex = true;

                            break;
                        }
                    }
                }

                break;
            }
        }

        if( !bSetSelectIndex )
        {
            optionIndex +=
                ( rShaderSelect.bOptional ? rShaderSelect.choices.GetSize() * optionIndexMultiplier : 0 );
        }

        optionIndexMultiplier *= rShaderSelect.choices.GetSize() + rShaderSelect.bOptional;
    }

    return optionIndex;
}
예제 #8
0
파일: Shader.cpp 프로젝트: euler0/Helium
/// Get a unique index associated with a specific set of shader preprocessor options.
///
/// Note that this will always attempt to match up a valid index, even if invalid options are specified or select
/// options are missing.
///
/// @param[in] shaderType       Type of shader.
/// @param[in] pToggleNames     List of enabled shader toggles.
/// @param[in] toggleNameCount  Number of names in the toggle name array.
/// @param[in] pSelectPairs     List of shader selection pair values.
/// @param[in] selectPairCount  Number of shader selection pair values in the given array.
///
/// @return  Index to use for the specified options.
size_t Shader::Options::GetOptionSetIndex(
    RShader::EType shaderType,
    const Name* pToggleNames,
    size_t toggleNameCount,
    const SelectPair* pSelectPairs,
    size_t selectPairCount ) const
{
    HELIUM_ASSERT( static_cast< size_t >( shaderType ) < static_cast< size_t >( RShader::TYPE_MAX ) );
    HELIUM_ASSERT( pToggleNames || toggleNameCount == 0 );
    HELIUM_ASSERT( pSelectPairs || selectPairCount == 0 );

    uint32_t shaderTypeMask = ( 1 << shaderType );

    size_t optionIndex = 0;
    size_t optionIndexMultiplier = 1;

    size_t shaderToggleCount = m_toggles.GetSize();
    for( size_t shaderToggleIndex = 0; shaderToggleIndex < shaderToggleCount; ++shaderToggleIndex )
    {
        const Toggle& rShaderToggle = m_toggles[ shaderToggleIndex ];
        if( !( rShaderToggle.shaderTypeFlags & shaderTypeMask ) )
        {
            continue;
        }

        Name shaderToggleName = rShaderToggle.name;
        for( size_t enabledToggleIndex = 0; enabledToggleIndex < toggleNameCount; ++enabledToggleIndex )
        {
            if( pToggleNames[ enabledToggleIndex ] == shaderToggleName )
            {
                optionIndex |= optionIndexMultiplier;

                break;
            }
        }

        optionIndexMultiplier <<= 1;
    }

    size_t shaderSelectCount = m_selects.GetSize();
    for( size_t shaderSelectIndex = 0; shaderSelectIndex < shaderSelectCount; ++shaderSelectIndex )
    {
        const Select& rShaderSelect = m_selects[ shaderSelectIndex ];
        if( !( rShaderSelect.shaderTypeFlags & shaderTypeMask ) )
        {
            continue;
        }

        Name shaderSelectName = rShaderSelect.name;

        bool bSetSelectIndex = false;
        for( size_t selectPairIndex = 0; selectPairIndex < selectPairCount; ++selectPairIndex )
        {
            const SelectPair& rPair = pSelectPairs[ selectPairIndex ];
            if( rPair.name == shaderSelectName )
            {
                const DynArray< Name >& rShaderSelectChoices = rShaderSelect.choices;
                size_t shaderSelectChoiceCount = rShaderSelectChoices.GetSize();

                Name targetChoiceName = rPair.choice;
                if( !targetChoiceName.IsEmpty() )
                {
                    for( size_t shaderSelectChoiceIndex = 0;
                        shaderSelectChoiceIndex < shaderSelectChoiceCount;
                        ++shaderSelectChoiceIndex )
                    {
                        if( rShaderSelectChoices[ shaderSelectChoiceIndex ] == targetChoiceName )
                        {
                            optionIndex += shaderSelectChoiceIndex * optionIndexMultiplier;
                            bSetSelectIndex = true;

                            break;
                        }
                    }
                }

                break;
            }
        }

        if( !bSetSelectIndex )
        {
            optionIndex +=
                ( rShaderSelect.bOptional ? rShaderSelect.choices.GetSize() * optionIndexMultiplier : 0 );
        }

        optionIndexMultiplier *= rShaderSelect.choices.GetSize() + rShaderSelect.bOptional;
    }

    return optionIndex;
}
예제 #9
0
/// Synchronize the shader parameter list with those provided by the selected shader variant.
///
/// @see SynchronizeFloatVectorParameters(), SynchronizeTextureParameters()
void Material::SynchronizeShaderParameters()
{
    Shader* pShader = m_spShader;
    if( !pShader )
    {
        m_float1Parameters.Clear();
        m_float2Parameters.Clear();
        m_float3Parameters.Clear();
        m_float4Parameters.Clear();
        m_textureParameters.Clear();
    }

    // Synchronize floating-point constant parameters.
    Name parameterConstantBufferName = GetParameterConstantBufferName();

    size_t existingFloat1Count = m_float1Parameters.GetSize();
    size_t existingFloat2Count = m_float2Parameters.GetSize();
    size_t existingFloat3Count = m_float3Parameters.GetSize();
    size_t existingFloat4Count = m_float4Parameters.GetSize();

    DynamicArray< Float1Parameter > newFloat1Parameters;
    DynamicArray< Float2Parameter > newFloat2Parameters;
    DynamicArray< Float3Parameter > newFloat3Parameters;
    DynamicArray< Float4Parameter > newFloat4Parameters;
    for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_shaderVariants ); ++shaderTypeIndex )
    {
        ShaderVariant* pShaderVariant = m_shaderVariants[ shaderTypeIndex ];
        if( !pShaderVariant )
        {
            continue;
        }

        const ShaderConstantBufferInfoSet* pBufferSet = pShaderVariant->GetConstantBufferInfoSet( 0 );
        if( !pBufferSet )
        {
            continue;
        }

        bool bCheckDuplicates =
            ( !newFloat1Parameters.IsEmpty() || !newFloat2Parameters.IsEmpty() || !newFloat3Parameters.IsEmpty() ||
            !newFloat4Parameters.IsEmpty() );

        const DynamicArray< ShaderConstantBufferInfo >& rBuffers = pBufferSet->buffers;
        size_t bufferCount = rBuffers.GetSize();
        for( size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex )
        {
            const ShaderConstantBufferInfo& rBufferInfo = rBuffers[ bufferIndex ];
            if( rBufferInfo.name != parameterConstantBufferName )
            {
                continue;
            }

            const DynamicArray< ShaderConstantInfo >& rConstants = rBufferInfo.constants;
            size_t constantCount = rConstants.GetSize();
            for( size_t constantIndex = 0; constantIndex < constantCount; ++constantIndex )
            {
                const ShaderConstantInfo& rConstantInfo = rConstants[ constantIndex ];

                // Constants must be between 1 and 4 floating-point values.
                uint16_t constantSize = rConstantInfo.usedSize;
                if( constantSize < sizeof( float32_t ) || constantSize > sizeof( float32_t ) * 4 )
                {
                    continue;
                }

                Name constantName = rConstantInfo.name;

                size_t parameterIndex;
                if( bCheckDuplicates )
                {
                    size_t parameterCount = newFloat1Parameters.GetSize();
                    for( parameterIndex = 0; parameterIndex < parameterCount; ++parameterIndex )
                    {
                        if( newFloat1Parameters[ parameterIndex ].name == constantName )
                        {
                            break;
                        }
                    }

                    if( parameterIndex < parameterCount )
                    {
                        continue;
                    }

                    parameterCount = newFloat2Parameters.GetSize();
                    for( parameterIndex = 0; parameterIndex < parameterCount; ++parameterIndex )
                    {
                        if( newFloat2Parameters[ parameterIndex ].name == constantName )
                        {
                            break;
                        }
                    }

                    if( parameterIndex < parameterCount )
                    {
                        continue;
                    }

                    parameterCount = newFloat3Parameters.GetSize();
                    for( parameterIndex = 0; parameterIndex < parameterCount; ++parameterIndex )
                    {
                        if( newFloat3Parameters[ parameterIndex ].name == constantName )
                        {
                            break;
                        }
                    }

                    if( parameterIndex < parameterCount )
                    {
                        continue;
                    }

                    parameterCount = newFloat4Parameters.GetSize();
                    for( parameterIndex = 0; parameterIndex < parameterCount; ++parameterIndex )
                    {
                        if( newFloat4Parameters[ parameterIndex ].name == constantName )
                        {
                            break;
                        }
                    }

                    if( parameterIndex < parameterCount )
                    {
                        continue;
                    }
                }

                Simd::Vector4 newValue( 0.0f );
                for( parameterIndex = 0; parameterIndex < existingFloat1Count; ++parameterIndex )
                {
                    const Float1Parameter& rExistingParameter = m_float1Parameters[ parameterIndex ];
                    if( rExistingParameter.name == constantName )
                    {
                        newValue.SetElement( 0, rExistingParameter.value );

                        break;
                    }
                }

                if( parameterIndex >= existingFloat1Count )
                {
                    for( parameterIndex = 0; parameterIndex < existingFloat2Count; ++parameterIndex )
                    {
                        const Float2Parameter& rExistingParameter = m_float2Parameters[ parameterIndex ];
                        if( rExistingParameter.name == constantName )
                        {
                            newValue.SetElement( 0, rExistingParameter.value.GetX() );
                            newValue.SetElement( 1, rExistingParameter.value.GetY() );

                            break;
                        }
                    }

                    if( parameterIndex >= existingFloat2Count )
                    {
                        for( parameterIndex = 0; parameterIndex < existingFloat3Count; ++parameterIndex )
                        {
                            const Float3Parameter& rExistingParameter = m_float3Parameters[ parameterIndex ];
                            if( rExistingParameter.name == constantName )
                            {
                                newValue.SetElement( 0, rExistingParameter.value.GetElement( 0 ) );
                                newValue.SetElement( 1, rExistingParameter.value.GetElement( 1 ) );
                                newValue.SetElement( 2, rExistingParameter.value.GetElement( 2 ) );

                                break;
                            }
                        }

                        if( parameterIndex >= existingFloat3Count )
                        {
                            for( parameterIndex = 0; parameterIndex < existingFloat4Count; ++parameterIndex )
                            {
                                const Float4Parameter& rExistingParameter =
                                    m_float4Parameters[ parameterIndex ];
                                if( rExistingParameter.name == constantName )
                                {
                                    newValue = rExistingParameter.value;

                                    break;
                                }
                            }
                        }
                    }
                }

                if( constantSize < sizeof( float32_t ) * 2 )
                {
                    Float1Parameter* pParameter = newFloat1Parameters.New();
                    HELIUM_ASSERT( pParameter );
                    pParameter->name = constantName;
                    pParameter->value = newValue.GetElement( 0 );
                }
                else if( constantSize < sizeof( float32_t ) * 3 )
                {
                    Float2Parameter* pParameter = newFloat2Parameters.New();
                    HELIUM_ASSERT( pParameter );
                    pParameter->name = constantName;
                    pParameter->value = Simd::Vector2( newValue.GetElement( 0 ), newValue.GetElement( 1 ) );
                }
                else if( constantSize < sizeof( float32_t ) * 4 )
                {
                    Float3Parameter* pParameter = newFloat3Parameters.New();
                    HELIUM_ASSERT( pParameter );
                    pParameter->name = constantName;
                    pParameter->value =
                        Simd::Vector3( newValue.GetElement( 0 ), newValue.GetElement( 1 ), newValue.GetElement( 2 ) );
                }
                else
                {
                    Float4Parameter* pParameter = newFloat4Parameters.New();
                    HELIUM_ASSERT( pParameter );
                    pParameter->name = constantName;
                    pParameter->value = newValue;
                }
            }
        }
    }

    newFloat1Parameters.Trim();
    newFloat2Parameters.Trim();
    newFloat3Parameters.Trim();
    newFloat4Parameters.Trim();
    m_float1Parameters.Swap( newFloat1Parameters );
    m_float2Parameters.Swap( newFloat2Parameters );
    m_float3Parameters.Swap( newFloat3Parameters );
    m_float4Parameters.Swap( newFloat4Parameters );
    newFloat1Parameters.Clear();
    newFloat2Parameters.Clear();
    newFloat3Parameters.Clear();
    newFloat4Parameters.Clear();

    // Synchronize texture parameters.
    size_t existingTextureCount = m_textureParameters.GetSize();

    DynamicArray< TextureParameter > newTextureParameters;
    for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_shaderVariants ); ++shaderTypeIndex )
    {
        ShaderVariant* pShaderVariant = m_shaderVariants[ shaderTypeIndex ];
        if( !pShaderVariant )
        {
            continue;
        }

        const ShaderTextureInfoSet* pTextureSet = pShaderVariant->GetTextureInfoSet( 0 );
        if( !pTextureSet )
        {
            continue;
        }

        bool bCheckDuplicates = !newTextureParameters.IsEmpty();

        const DynamicArray< ShaderTextureInfo >& rTextureInputs = pTextureSet->inputs;
        size_t textureInputCount = rTextureInputs.GetSize();
        for( size_t textureIndex = 0; textureIndex < textureInputCount; ++textureIndex )
        {
            const ShaderTextureInfo& rTextureInfo = rTextureInputs[ textureIndex ];

            // Ignore textures prefixed with an underscore, as they are reserved for system use.
            Name textureInputName = rTextureInfo.name;
            if( !textureInputName.IsEmpty() && ( *textureInputName )[ 0 ] == TXT( '_' ) )
            {
                continue;
            }

            size_t parameterIndex;
            if( bCheckDuplicates )
            {
                size_t textureParameterCount = newTextureParameters.GetSize();
                for( parameterIndex = 0; parameterIndex < textureParameterCount; ++parameterIndex )
                {
                    if( newTextureParameters[ parameterIndex ].name == textureInputName )
                    {
                        break;
                    }
                }

                if( parameterIndex < textureParameterCount )
                {
                    continue;
                }
            }

            TextureParameter* pParameter = newTextureParameters.New();
            HELIUM_ASSERT( pParameter );
            pParameter->name = textureInputName;

            for( parameterIndex = 0; parameterIndex < existingTextureCount; ++parameterIndex )
            {
                const TextureParameter& rTextureParameter = m_textureParameters[ parameterIndex ];
                if( rTextureParameter.name == textureInputName )
                {
                    pParameter->value = rTextureParameter.value;

                    break;
                }
            }
        }
    }

    newTextureParameters.Trim();
    m_textureParameters.Swap( newTextureParameters );
    newTextureParameters.Clear();
}
예제 #10
0
/// Create a type object.
///
/// @param[in] name          Type name.
/// @param[in] pTypePackage  Package in which the template object should be stored.
/// @param[in] pParent       Parent type.
/// @param[in] pTemplate     Template object.
/// @param[in] flags         Type flags.
///
/// @return  Pointer to the type object if created successfully, null if not.
///
/// @see Unregister()
// PMD: Removing const because:
// - Objects must be able to have properties of the same type as the outer type (i.e. Asset has reference to Asset that is the template)
// - So, s_MetaClass must be set before calling PopulateMetaType
// - So, this function must return a pointer that PopulateMetaType can work on, rather than calling PopulateMetaType directly
//   - If not for this restriction, I'd want to see if we could call MetaClass::Create and Composite::Create, rather than doing duplicate set-up work here
// - To prevent un-consting parameter to PopulateMetaType, making AssetType return non-const
AssetType* AssetType::Create(
	const Reflect::MetaClass* pClass,
	Package* pTypePackage,
	const AssetType* pParent,
	Asset* pTemplate,
	uint32_t flags )
{
	HELIUM_ASSERT( pClass );
	HELIUM_ASSERT( pTypePackage );
	HELIUM_ASSERT( pTemplate );

	Name name;
	name.Set( pClass->m_Name );
	HELIUM_ASSERT( !name.IsEmpty() );

	// Register the template object with the object system.
	if( !Asset::RegisterObject( pTemplate ) )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "AssetType::Initialize(): Failed to register type \"%s\" template object.\n" ),
			*name );

		return NULL;
	}

	// Set up the template object name, and set this object as its parent.
	Asset::RenameParameters nameParameters;
	nameParameters.name = name;
	nameParameters.spOwner = pTypePackage;
	if( !pTemplate->Rename( nameParameters ) )
	{
		HELIUM_TRACE(
			TraceLevels::Error,
			TXT( "AssetType::Initialize(): Failed to set type \"%s\" template object name and owner.\n" ),
			*name );

		Asset::UnregisterObject( pTemplate );

		return NULL;
	}

	// Flag the object as the default template object for the type being created.
	pTemplate->SetFlags( 
		Asset::FLAG_DEFAULT_TEMPLATE | 
		Asset::FLAG_TRANSIENT | 
		Asset::FLAG_PRELOADED | 
		Asset::FLAG_LINKED |
		Asset::FLAG_PRECACHED |
		Asset::FLAG_LOADED);

	// Create the type object and store its parameters.
	AssetType* pType = new AssetType;
	HELIUM_ASSERT( pType );
	pType->m_class = pClass;
	pClass->m_Tag = pType;
	const_cast< Reflect::MetaClass* >( pType->m_class )->m_Default = pTemplate;
	const_cast< Reflect::MetaClass* >( pType->m_class )->MetaStruct::m_Default = pTemplate;
	pType->m_name = name;
	pType->m_flags = flags;

	// Lazily initialize the lookup map.  Note that this is not inherently thread-safe, but there should always be
	// at least one type registered before any sub-threads are spawned.
	if( !sm_pLookupMap )
	{
		sm_pLookupMap = new LookupMap;
		HELIUM_ASSERT( sm_pLookupMap );
	}

	// Register the type (note that a type with the same name should not already exist in the lookup map).
	LookupMap::Iterator typeIterator;
	HELIUM_VERIFY( sm_pLookupMap->Insert( typeIterator, KeyValue< Name, AssetTypePtr >( pType->GetName(), pType ) ) );

	return pType;
}