// Retrieve specified pixel shader
//-----------------------------------------------------------------------------
CPUTResult CPUTAssetLibraryDX11::GetPixelShader(
    const cString        &name,
    ID3D11Device         *pD3dDevice,
    const cString        &shaderMain,
    const cString        &shaderProfile,
    CPUTPixelShaderDX11 **ppPixelShader,
    bool                  nameIsFullPathAndFilename
)
{
    CPUTResult result = CPUT_SUCCESS;
    cString finalName;
    if( name.at(0) == '$' )
    {
        finalName = name;
    } else
    {
        // Resolve name to absolute path
        CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
        pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mShaderDirectoryName + name), &finalName);
    }

    // see if the shader is already in the library
    void *pShader = FindPixelShader(finalName + shaderMain + shaderProfile, true);
    if(NULL!=pShader)
    {
        *ppPixelShader = (CPUTPixelShaderDX11*) pShader;
        (*ppPixelShader)->AddRef();
        return result;
    }
    *ppPixelShader = CPUTPixelShaderDX11::CreatePixelShader( finalName, pD3dDevice, shaderMain, shaderProfile );

    return result;
}
示例#2
0
// Set where CPUT will look for it's button images, fonts, etc
//-----------------------------------------------------------------------------
CPUTResult CPUT_DX11::SetCPUTResourceDirectory(const cString ResourceDirectory)
{
    // check to see if the specified directory is valid
    CPUTResult result = CPUT_SUCCESS;

    // resolve the directory to a full path
    cString fullPath;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    result = pServices->ResolveAbsolutePathAndFilename(ResourceDirectory, &fullPath);
    if(CPUTFAILED(result))
    {
        return result;
    }

    // check existence of directory
    result = pServices->DoesDirectoryExist(fullPath);
    if(CPUTFAILED(result))
    {
        return result;
    }

    // set the resource directory (absolute path)
    mResourceDirectory = fullPath;

    // tell the gui system where to look for it's resources
    // todo: do we want to force a flush/reload of all resources (i.e. change control graphics)
    result = CPUTGuiControllerDX11::GetController()->SetResourceDirectory(ResourceDirectory);

    return result;
}
// Get CPUTModel from asset library
// If the model exists, then the existing model is Addref'ed and returned
//-----------------------------------------------------------------------------
CPUTModel *CPUTAssetLibrary::GetModel(const cString &name, bool nameIsFullPathAndFilename)
{
    // Resolve name to absolute path before searching
    cString absolutePathAndFilename;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mModelDirectoryName + name + _L(".mdl")), &absolutePathAndFilename);
    absolutePathAndFilename = nameIsFullPathAndFilename ? name : absolutePathAndFilename;

    // If we already have one by this name, then return it
    CPUTModel *pModel = FindModel(absolutePathAndFilename, true);
    if(NULL!=pModel)
    {
        pModel->AddRef();
        return pModel;
    }

    // Looks like no one calls GetModel().  Or, they never call it for missing models.
#if TODO // delegate
    // Model was not in the library, so create and load a new model
    pModel = new CPUTModel();
    pModel->LoadModelPayload(absolutePathAndFilename);
    AddModel(name, pModel);

    return CPUTModel::CreateMode( absolutePathAndFilename, aboslutePathAndFilename );
#endif

    return pModel;
}
// sets the resource directory to use when loading GUI resources
//-----------------------------------------------------------------------------
CPUTResult CPUTGuiController::SetResourceDirectory(const cString ResourceDirectory)
{
    // check to see if the specified directory is valid
    CPUTResult result = CPUT_SUCCESS;

    // resolve the directory to a full path
    cString FullPath;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    result = pServices->ResolveAbsolutePathAndFilename(ResourceDirectory, &FullPath);
    if(CPUTFAILED(result))
    {
        return result;
    }

    // check existence of directory
    result = pServices->DoesDirectoryExist(FullPath);
    if(CPUTFAILED(result))
    {
        return result;
    }

    // set the resource directory (absolute path)
    mResourceDirectory = FullPath;

    return result;
}
// TODO: All of these Get() functions look very similar.
// Keep them all for their interface, but have them call a common function
//-----------------------------------------------------------------------------
CPUTMaterial *CPUTAssetLibrary::GetMaterial(const cString &name, bool nameIsFullPathAndFilename, const cString &modelSuffix, const cString &meshSuffix)
{
    // Resolve name to absolute path before searching
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    cString absolutePathAndFilename;
    pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mMaterialDirectoryName + name + _L(".mtl")), &absolutePathAndFilename);

    // If we already have one by this name, then return it
    CPUTMaterial *pMaterial = FindMaterial(absolutePathAndFilename, true);
    if(NULL==pMaterial)
    {
        // We don't already have it in the library, so create it.
        pMaterial = CPUTMaterial::CreateMaterial( absolutePathAndFilename, modelSuffix, meshSuffix );
        return pMaterial;
    }
    else if( (0==modelSuffix.length()) && !pMaterial->MaterialRequiresPerModelPayload() )
    {
        // This material doesn't have per-model elements, so we don't need to clone it.
        pMaterial->AddRef();
        return pMaterial;
    }

#ifdef _DEBUG
    // We need to clone the material.  Do that by loading it again, but with a different name.
    // Add the model's suffix (address as string, plus model's material array index as string)
    CPUTMaterial *pUniqueMaterial = FindMaterial(absolutePathAndFilename + modelSuffix + meshSuffix, true);
    ASSERT( NULL == pUniqueMaterial, _L("Unique material already not unique: ") + absolutePathAndFilename + modelSuffix + meshSuffix );
#endif

    CPUTMaterial *pClonedMaterial = pMaterial->CloneMaterial( absolutePathAndFilename, modelSuffix, meshSuffix );
    AddMaterial( absolutePathAndFilename + modelSuffix + meshSuffix, pClonedMaterial );

    return pClonedMaterial;
}
//-----------------------------------------------------------------------------
CPUTFont *CPUTAssetLibrary::GetFont(const cString &name )
{
    // Resolve name to absolute path
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    cString absolutePathAndFilename;
    pServices->ResolveAbsolutePathAndFilename( (mFontDirectoryName + name), &absolutePathAndFilename);

    // If we already have one by this name, then return it
    CPUTFont *pFont = FindFont(absolutePathAndFilename, true);
    if(NULL==pFont)
    {
        return CPUTFont::CreateFont( name, absolutePathAndFilename);
    }
    pFont->AddRef();
    return pFont;
}
// Retrieve specified pixel shader
// TODO: Delegate creation to asset (AssetLibrary shouldn't know the nitty-gritty details of how to create an asset)
//-----------------------------------------------------------------------------
CPUTResult CPUTAssetLibraryOGLES::GetPixelShader(
    const cString        &name,
    const cString        &shaderMain,
    const cString        &shaderProfile,
    CPUTPixelShaderOGLES **ppPixelShader,
    bool                  nameIsFullPathAndFilename
)
{
    CPUTResult result = CPUT_SUCCESS;
    
    // Resolve name to absolute path before searching
    cString absolutePathAndFilename;
    CPUTOSServices* pServices = CPUTOSServices::GetOSServices();
    pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (m_ShaderDirectoryName + name), &absolutePathAndFilename);

    // see if the shader is already in the library
    void *pShader = FindPixelShader(absolutePathAndFilename);
    if(NULL!=pShader)
    {
        *ppPixelShader = (CPUTPixelShaderOGLES*) pShader;
        (*ppPixelShader)->AddRef();
        return result;
    }

    // load the pixel shader as null-terminated char* string
    void* pShaderString=NULL;
    result = LoadShaderFileString(absolutePathAndFilename, &pShaderString);
    ASSERT( CPUTSUCCESS(result), _L("Error loading pixel shader: ")+name );

    // compile the pixel/fragment shader
    GLuint NewPixelShaderID = CompileShader(GL_FRAGMENT_SHADER, pShaderString);
    ASSERT( (0!=NewPixelShaderID), _L("Error compiling pixel shader: "+name) );

    // delete the shader's string now that it's no longer needed
    delete [] pShaderString;
    
    // store this new shader
    CPUTPixelShaderOGLES *pNewCPUTPixelShader = new CPUTPixelShaderOGLES( NewPixelShaderID );

    // add shader to library
    AddPixelShader(absolutePathAndFilename, pNewCPUTPixelShader);
    
    // return the shader 
    *ppPixelShader = pNewCPUTPixelShader;

    return result;
}
//-----------------------------------------------------------------------------
CPUTAssetSet *CPUTAssetLibrary::GetAssetSet( const cString &name, bool nameIsFullPathAndFilename )
{
    // Resolve the absolute path
    cString absolutePathAndFilename;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename ? name
        : (mAssetSetDirectoryName + name + _L(".set")), &absolutePathAndFilename );
    absolutePathAndFilename = nameIsFullPathAndFilename ? name : absolutePathAndFilename;

    CPUTAssetSet *pAssetSet = FindAssetSet(absolutePathAndFilename, true);
    if(NULL == pAssetSet)
    {
        return CPUTAssetSet::CreateAssetSet( name, absolutePathAndFilename );
    }
    pAssetSet->AddRef();
    return pAssetSet;
}
// Find an asset in a specific library
// ** Does not Addref() returned items **
// Asset library doesn't care if we're using absolute paths for names or not, it
// just adds/finds/deletes the matching string literal.
//-----------------------------------------------------------------------------
void *CPUTAssetLibrary::FindAsset(const cString &name, CPUTAssetListEntry *pList, bool nameIsFullPathAndFilename)
{
    cString absolutePathAndFilename;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename ? name : (mAssetSetDirectoryName + name), &absolutePathAndFilename);
    absolutePathAndFilename = nameIsFullPathAndFilename ? name : absolutePathAndFilename;

    UINT hash = CPUTComputeHash( absolutePathAndFilename );
    while(NULL!=pList)
    {
        if( hash == pList->hash && (0 == _wcsicmp( absolutePathAndFilename.data(), pList->name.data() )) )
        {
            return (void*)pList->pData;
        }
        pList = pList->pNext;
    }
    return NULL;
}
//-----------------------------------------------------------------------------
CPUTTexture *CPUTAssetLibrary::GetTexture(const cString &name, bool nameIsFullPathAndFilename, bool loadAsSRGB )
{
    cString finalName;
    if( name.at(0) == '$' )
    {
        finalName = name;
    } else
    {
        // Resolve name to absolute path
        CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
        pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mTextureDirectoryName + name), &finalName);
    }
    // If we already have one by this name, then return it
    CPUTTexture *pTexture = FindTexture(finalName, true);
    if(NULL==pTexture)
    {
        return CPUTTexture::CreateTexture( name, finalName, loadAsSRGB);
    }
    pTexture->AddRef();
    return pTexture;
}
//-----------------------------------------------------------------------------
CPUTRenderStateBlock *CPUTAssetLibrary::GetRenderStateBlock(const cString &name, bool nameIsFullPathAndFilename )
{
    // Resolve name to absolute path before searching
    cString finalName;
    if( name.at(0) == '$' )
    {
        finalName = name;
    } else
    {
        // Resolve name to absolute path
        CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
        pServices->ResolveAbsolutePathAndFilename( nameIsFullPathAndFilename? name : (mShaderDirectoryName + name), &finalName);
    }

    // see if the render state block is already in the library
    CPUTRenderStateBlock *pRenderStateBlock = FindRenderStateBlock(finalName, true);
    if(NULL==pRenderStateBlock)
    {
        return CPUTRenderStateBlock::CreateRenderStateBlock( name, finalName );
    }
    pRenderStateBlock->AddRef();
    return pRenderStateBlock;
}
//-----------------------------------------------
HRESULT CPUTRenderTargetColor::CreateRenderTarget(
    cString     textureName,
    UINT        width,
    UINT        height,
    DXGI_FORMAT colorFormat,
    UINT        multiSampleCount,
    bool        createUAV,
    bool        recreate
)
{
    HRESULT result;

    mName             = textureName;
    mWidth            = width;
    mHeight           = height;
    mColorFormat      = colorFormat;
    mMultiSampleCount = multiSampleCount;

    CPUTAssetLibrary *pAssetLibrary = CPUTAssetLibrary::GetAssetLibrary();
    CPUTOSServices   *pServices     = CPUTOSServices::GetOSServices();

    // Create the color texture
    int createFlags = createUAV 
        ? D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS
        : D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;

    mColorDesc = CD3D11_TEXTURE2D_DESC(
        colorFormat,
        width,
        height,
        1, // Array Size
        1, // MIP Levels
        createFlags,
        D3D11_USAGE_DEFAULT,
        0,
        mMultiSampleCount, 0
    );

    ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice();

    // If MSAA enabled, then create MSAA texture
    if( mMultiSampleCount>1 )
    {
        result = pD3dDevice->CreateTexture2D( &mColorDesc, NULL, &mpColorTextureDXMSAA );
        ASSERT( SUCCEEDED(result), _L("Failed creating MSAA render target texture") );

        D3D11_SHADER_RESOURCE_VIEW_DESC srDesc = { colorFormat, D3D11_SRV_DIMENSION_TEXTURE2DMS, 0 };
        srDesc.Texture2D.MipLevels = 1;
        result = pD3dDevice->CreateShaderResourceView( mpColorTextureDXMSAA, &srDesc, &mpColorSRVMSAA );
        ASSERT( SUCCEEDED(result), _L("Failed creating MSAA render target shader resource view") );
        CPUTSetDebugName( mpColorSRVMSAA, textureName + _L(" ColorMSAA") );

        if( !recreate )
        {
            cString msaaName = mName + _L("_MSAA");
            mpColorTextureMSAA = new CPUTTextureDX11( msaaName );

            // If the name starts with a '$', then its an internal texture (has no filesystem path).
            // Otherwise, its a file, so prepend filesystem path
            CPUTAssetLibrary *pAssetLibrary = CPUTAssetLibrary::GetAssetLibrary();
            cString finalName;
            if( mName.at(0) == '$' )
            {
                finalName = msaaName;
            }else
            {
                pServices->ResolveAbsolutePathAndFilename( (pAssetLibrary->GetTextureDirectory() + msaaName), &finalName);
            }
            pAssetLibrary->AddTexture( finalName, mpColorTextureMSAA );
        }
        ((CPUTTextureDX11*)mpColorTextureMSAA)->SetTextureAndShaderResourceView( mpColorTextureDXMSAA, mpColorSRVMSAA );
    }
    
    // Create non-MSAA texture.  If we're MSAA, then we'll resolve into this.  If not, then we'll render directly to this one.
    mColorDesc.SampleDesc.Count = 1;
    result = pD3dDevice->CreateTexture2D( &mColorDesc, NULL, &mpColorTextureDX );
    ASSERT( SUCCEEDED(result), _L("Failed creating render target texture") );

    // Create the shader-resource view from the non-MSAA texture
    D3D11_SHADER_RESOURCE_VIEW_DESC srDesc = { colorFormat, D3D11_SRV_DIMENSION_TEXTURE2D, 0 };
    srDesc.Texture2D.MipLevels = 1;
    result = pD3dDevice->CreateShaderResourceView( mpColorTextureDX, &srDesc, &mpColorSRV );
    ASSERT( SUCCEEDED(result), _L("Failed creating render target shader resource view") );
    CPUTSetDebugName( mpColorSRV, textureName + _L(" Color") );

    mHasUav = createUAV; // Remember, so we know to recreate it (or not) on RecreateRenderTarget()
    if( createUAV )
    {
        // D3D11_SHADER_RESOURCE_VIEW_DESC srDesc = { colorFormat, D3D_SRV_DIMENSION_BUFFER, 0 };
        D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
        memset( &uavDesc, 0, sizeof(uavDesc) );
        uavDesc.Format = colorFormat;
        uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
        uavDesc.Texture2D.MipSlice = 0;
        result = pD3dDevice->CreateUnorderedAccessView( mpColorTextureDX, &uavDesc, &mpColorUAV );
        ASSERT( SUCCEEDED(result), _L("Failed creating render target buffer shader resource view") );
        CPUTSetDebugName( mpColorUAV, textureName + _L(" Color Buffer") );
    }
    if( !recreate )
    {
        mpColorTexture = new CPUTTextureDX11(mName);
        pAssetLibrary->AddTexture( mName, mpColorTexture );

        mpColorBuffer = new CPUTBufferDX11(mName, NULL, mpColorUAV); // We don't have an ID3D11Buffer, but we want to track this UAV as if the texture was a buffer.
        pAssetLibrary->AddBuffer( mName, mpColorBuffer );
    }
    ((CPUTTextureDX11*)mpColorTexture)->SetTextureAndShaderResourceView( mpColorTextureDX, mpColorSRV);

    // Choose our render target.  If MSAA, then use the MSAA texture, and use resolve to fill the non-MSAA texture.
    ID3D11Texture2D *pColorTexture = (mMultiSampleCount>1) ? mpColorTextureDXMSAA : mpColorTextureDX;
    result = pD3dDevice->CreateRenderTargetView( pColorTexture, NULL, &mpColorRenderTargetView );
    ASSERT( SUCCEEDED(result), _L("Failed creating render target view") );
    CPUTSetDebugName( mpColorRenderTargetView, mName );

    return S_OK;
}
// Load and register all the resources needed by the GUI system
//-----------------------------------------------------------------------------
CPUTResult CPUTGuiControllerDX11::RegisterGUIResources(ID3D11DeviceContext *pImmediateContext, cString VertexShaderFilename, cString PixelShaderFilename, cString RenderStateFile, cString DefaultFontFilename, cString ControlAtlasTexture)
{
    if(NULL==pImmediateContext)
    {
        return CPUT_ERROR_INVALID_PARAMETER;
    }
    CPUTResult result;
    HRESULT hr;
    ID3D11Device *pD3dDevice = NULL;
    CPUTOSServices *pServices = NULL;
    CPUTAssetLibraryDX11 *pAssetLibrary = NULL;
    cString ErrorMessage;

    // Get the services/resource pointers we need
    pServices = CPUTOSServices::GetOSServices();
    pImmediateContext->GetDevice(&pD3dDevice);
    pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibraryDX11::GetAssetLibrary();

    // Get the resource directory
    cString ResourceDirectory;
    CPUTGuiControllerDX11::GetController()->GetResourceDirectory(ResourceDirectory);

    // 1. Load the renderstate configuration for the GUI system
    mpGUIRenderStateBlock = (CPUTRenderStateBlockDX11*) pAssetLibrary->GetRenderStateBlock(ResourceDirectory+RenderStateFile); 
    ASSERT(mpGUIRenderStateBlock, _L("Error loading the render state file (.rs) needed for the CPUT GUI system"));
    

    // 2. Store the shader path from AssetLibrary, change it to OUR resource directory
    cString OriginalAssetLibraryDirectory = pAssetLibrary->GetShaderDirectory();
    pAssetLibrary->SetShaderDirectoryName(ResourceDirectory);
    

    // 3. load the shaders for gui drawing
    // Load the GUI Vertex Shader
    cString FullPath, FinalPath;
    FullPath = mResourceDirectory + VertexShaderFilename;
    pServices->ResolveAbsolutePathAndFilename(FullPath, &FinalPath);
    result = pAssetLibrary->GetVertexShader(FinalPath, pD3dDevice, _L("VS"), _L("vs_4_0"), &mpGUIVertexShader, true);
    CPUTSetDebugName( mpGUIVertexShader->GetNativeVertexShader(), _L("GUIVertexShader"));
    if(CPUTFAILED(result))
    {
        ASSERT(CPUTSUCCESS(result), _L("Error loading the vertex shader needed for the CPUT GUI system."));
    }
    ID3DBlob *pVertexShaderBlob = mpGUIVertexShader->GetBlob();

    // Load the GUI Pixel Shader
    FullPath = mResourceDirectory + PixelShaderFilename;
    pServices->ResolveAbsolutePathAndFilename(FullPath, &FinalPath);
    result = pAssetLibrary->GetPixelShader(FinalPath, pD3dDevice, _L("PS"), _L("ps_4_0"), &mpGUIPixelShader, true);
    CPUTSetDebugName( mpGUIPixelShader->GetNativePixelShader(), _L("GUIPixelShader"));
    if(CPUTFAILED(result))
    {
        ASSERT(CPUTSUCCESS(result), _L("Error loading the pixel shader needed for the CPUT GUI system."));
    }

    // Restore the previous shader directory
    pAssetLibrary->SetShaderDirectoryName(OriginalAssetLibraryDirectory);
    

    // 4. Create the vertex layout description for all the GUI controls we'll draw
    // set vertex shader as active so we can configure it
    ID3D11VertexShader *pVertexShader = mpGUIVertexShader->GetNativeVertexShader();
    pImmediateContext->VSSetShader( pVertexShader, NULL, 0 );

    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },		
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = ARRAYSIZE( layout );

    // Create the input layout
    hr = pD3dDevice->CreateInputLayout( layout, numElements, pVertexShaderBlob->GetBufferPointer(), pVertexShaderBlob->GetBufferSize(), &mpVertexLayout );
    ASSERT( SUCCEEDED(hr), _L("Error creating CPUT GUI system input layout" ));
    CPUTSetDebugName( mpVertexLayout, _L("CPUT GUI InputLayout object"));
    

    // 5. create the vertex shader constant buffer pointers
    D3D11_BUFFER_DESC bd;
    ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof(GUIConstantBufferVS);
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bd.CPUAccessFlags = 0;
    hr = pD3dDevice->CreateBuffer( &bd, NULL, &mpConstantBufferVS );
    ASSERT( SUCCEEDED(hr), _L("Error creating constant buffer VS" ));
    CPUTSetDebugName( mpConstantBufferVS, _L("GUI ConstantBuffer"));
      
    // Set the texture directory for loading the control texture atlas
    pAssetLibrary->SetTextureDirectoryName(ResourceDirectory);

    // load the control atlas
    mpControlTextureAtlas = (CPUTTextureDX11*) pAssetLibrary->GetTexture(ControlAtlasTexture); 
    if(NULL==mpControlTextureAtlas)
    {
        return CPUT_TEXTURE_LOAD_ERROR;
    }
    mpControlTextureAtlasView = mpControlTextureAtlas->GetShaderResourceView();
    mpControlTextureAtlasView->AddRef();

    // restore the asset library's texture directory    
    pAssetLibrary->SetTextureDirectoryName(OriginalAssetLibraryDirectory);
    

    // 6. Load the font atlas
    // store the existing asset library font directory
    OriginalAssetLibraryDirectory = pAssetLibrary->GetFontDirectory(); 

    // set font directory to the resource directory
    pAssetLibrary->SetFontDirectoryName(ResourceDirectory);
    mpFont = (CPUTFontDX11*) pAssetLibrary->GetFont(DefaultFontFilename); 
    if(NULL==mpFont)
    {
        return CPUT_TEXTURE_LOAD_ERROR;
    }
    mpTextTextureAtlas = mpFont->GetAtlasTexture();
    mpTextTextureAtlas->AddRef();
    mpTextTextureAtlasView = mpFont->GetAtlasTextureResourceView();
    mpTextTextureAtlasView->AddRef();    

    // restore the asset library's font directory    
    pAssetLibrary->SetTextureDirectoryName(OriginalAssetLibraryDirectory);
    
    
    // 7. Set up the DirectX uber-buffers that the controls draw into
    int maxSize = max(CPUT_GUI_BUFFER_STRING_SIZE, CPUT_GUI_BUFFER_SIZE);
    maxSize = max(maxSize, CPUT_GUI_VERTEX_BUFFER_SIZE);    
    maxSize *= sizeof( CPUTGUIVertex );
    char *pZeroedBuffer= new char[maxSize];
    memset(pZeroedBuffer, 0, maxSize);

    // set up buffer description
    ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_VERTEX_BUFFER_SIZE; //mUberBufferIndex;
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    // initialization data (all 0's for now)
    D3D11_SUBRESOURCE_DATA InitData;
    ZeroMemory( &InitData, sizeof(InitData) );
    InitData.pSysMem = mpMirrorBuffer;

    // mpUberBuffer
    SAFE_RELEASE(mpUberBuffer);
    hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpUberBuffer );
    ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure"));
    CPUTSetDebugName(mpUberBuffer, _L("CPUT GUI: Control's main vertex buffer"));


    // mpTextUberBuffer
    bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_BUFFER_STRING_SIZE;
    hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpTextUberBuffer );
    ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure"));
    CPUTSetDebugName(mpTextUberBuffer, _L("CPUT GUI: control text vertex buffer"));


    // mpFocusedControlBuffer
    bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_VERTEX_BUFFER_SIZE;
    hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpFocusedControlBuffer );
    ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure"));
    CPUTSetDebugName(mpFocusedControlBuffer, _L("CPUT GUI: focused control images vertex buffer"));

    
    // mpFocusedControlTextBuffer
    bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_BUFFER_STRING_SIZE; //mFocusedControlTextBufferIndex;
    hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpFocusedControlTextBuffer );
    ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure"));
    CPUTSetDebugName(mpFocusedControlTextBuffer, _L("CPUT GUI: focused control text vertex buffer"));

    // mpFPSDirectXBuffer
    bd.ByteWidth = sizeof( CPUTGUIVertex ) * CPUT_GUI_BUFFER_STRING_SIZE;
    hr = pD3dDevice->CreateBuffer( &bd, &InitData, &mpFPSDirectXBuffer );
    ASSERT( !FAILED( hr ), _L("CPUT GUI FPS counter buffer creation failure"));
    CPUTSetDebugName(mpFPSDirectXBuffer, _L("CPUT GUI: FPS display text"));
    
    // no longer need the device - release it.
    SAFE_RELEASE(pD3dDevice);
    SAFE_DELETE_ARRAY(pZeroedBuffer);    


    // 8. Register all GUI sub-resources
    // Walk all the controls/fonts and have them register all their required static resources
    // Returning errors if you couldn't find your resources
    result = CPUTText::RegisterStaticResources();
    if(CPUTFAILED(result))
    {
        return result;
    }
    result = CPUTButton::RegisterStaticResources();
    if(CPUTFAILED(result))
    {
        return result;
    }
    result = CPUTCheckbox::RegisterStaticResources();
    if(CPUTFAILED(result))
    {
        return result;
    }
    result = CPUTSlider::RegisterStaticResources();
    if(CPUTFAILED(result))
    {
        return result;
    }
    result = CPUTDropdown::RegisterStaticResources();
    if(CPUTFAILED(result))
    {
        return result;
    }

    // create the FPS CPUTText object for drawing FPS
    mpFPSCounter = new CPUTText(_L("FPS:"), ID_CPUT_GUI_FPS_COUNTER, mpFont);
    mpFPSCounter->SetAutoArranged(false);
    mpFPSCounter->SetPosition(0,0);

    // start the timer
    mpFPSTimer->StartTimer();

    // done
    return CPUT_SUCCESS;
}