コード例 #1
0
ファイル: Shader.cpp プロジェクト: euler0/Helium
/// @copydoc GameObject::TryFinishPrecacheResourceData()
bool ShaderVariant::TryFinishPrecacheResourceData()
{
    Renderer* pRenderer = Renderer::GetStaticInstance();
    HELIUM_ASSERT( pRenderer );

    // Get the type of shader being loaded.
    Name variantName = GetName();
    tchar_t shaderTypeCharacter = ( *variantName )[ 0 ];

    RShader::EType shaderType;
    if( shaderTypeCharacter == TXT( 'v' ) )
    {
        shaderType = RShader::TYPE_VERTEX;
    }
    else
    {
        HELIUM_ASSERT( shaderTypeCharacter == TXT( 'p' ) );
        shaderType = RShader::TYPE_PIXEL;
    }

    // Wait for all async load requests to complete.
    bool bHavePendingLoad = false;

    size_t loadRequestCount = m_renderResourceLoads.GetSize();
    for( size_t loadRequestIndex = 0; loadRequestIndex < loadRequestCount; ++loadRequestIndex )
    {
        LoadData& rLoadData = m_renderResourceLoads[ loadRequestIndex ];
        if( IsInvalid( rLoadData.id ) )
        {
            continue;
        }

        if( !TryFinishLoadSubData( rLoadData.id ) )
        {
            bHavePendingLoad = true;

            continue;
        }

        SetInvalid( rLoadData.id );

        // Serialize the constant buffer information.
        BinaryDeserializer deserializer;
        deserializer.Prepare( rLoadData.pData, rLoadData.size );
        deserializer.BeginSerialize();
        m_constantBufferSets[ loadRequestIndex ].Serialize( deserializer );
        m_samplerInputSets[ loadRequestIndex ].Serialize( deserializer );
        m_textureInputSets[ loadRequestIndex ].Serialize( deserializer );
        size_t dataOffset = deserializer.GetCurrentOffset();
        deserializer.EndSerialize();

        // Apply padding for shader code alignment.
        dataOffset = Min( Align( dataOffset, sizeof( uint32_t ) ), rLoadData.size );

        // Create the shader resource.
        size_t shaderSize = rLoadData.size - dataOffset;
        const void* pShaderData = static_cast< const uint8_t* >( rLoadData.pData ) + dataOffset;

        RShaderPtr spShaderBase;
        if( shaderType == RShader::TYPE_VERTEX )
        {
            spShaderBase = pRenderer->CreateVertexShader( shaderSize, pShaderData );
        }
        else
        {
            spShaderBase = pRenderer->CreatePixelShader( shaderSize, pShaderData );
        }

        if( !spShaderBase )
        {
            HELIUM_TRACE(
                TRACE_ERROR,
                ( TXT( "ShaderVariant::TryFinishPrecacheResourceData(): Failed to create shader for sub-data %" )
                TPRIuSZ TXT( " of shader \"%s\".\n" ) ),
                loadRequestIndex,
                *GetPath().ToString() );
        }

        m_renderResources[ loadRequestIndex ] = spShaderBase;
    }

    if( bHavePendingLoad )
    {
        return false;
    }

    // All load requests have completed, so free all memory allocated for resource staging.
    m_renderResourceLoads.Clear();

    DefaultAllocator().Free( m_pRenderResourceLoadBuffer );
    m_pRenderResourceLoadBuffer = NULL;

    return true;
}