// Retrieve specified domain shader
//-----------------------------------------------------------------------------
CPUTResult CPUTAssetLibraryDX11::GetDomainShader(
    const cString           &name,
    ID3D11Device            *pD3dDevice,
    const cString           &shaderMain,
    const cString           &shaderProfile,
    CPUTDomainShaderDX11 **ppDomainShader,
    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 = FindDomainShader(finalName + shaderMain + shaderProfile, true);
    if(NULL!=pShader)
    {
        *ppDomainShader = (CPUTDomainShaderDX11*) pShader;
        (*ppDomainShader)->AddRef();
        return result;
    }
    *ppDomainShader = CPUTDomainShaderDX11::CreateDomainShader( finalName, pD3dDevice, shaderMain, shaderProfile );

    return result;
}
// 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;
}
//-----------------------------------------------------------------------------
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;
}
//
//   FUNCTION: InitInstance(HINSTANCE, int)
//   PURPOSE: Saves instance handle and creates main window
//   COMMENTS:
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//-----------------------------------------------------------------------------
BOOL WindowWinCPRTViewer::InitInstance(HINSTANCE hInstance, int nCmdShow, int windowWidth, int windowHeight)
{
   m_hInst = hInstance; // Store instance handle in our global variable

   LPCSTR lpTitle = m_AppTitle;

   if( (0==windowWidth) || (0==windowHeight) )
   {
       // zero sized windows means - you choose the size. :)
       CPUTOSServices* pServices = CPUTOSServices::GetOSServices();
       pServices->GetDesktopDimensions(windowWidth, windowHeight);
       
       // default window size will be 1/3 of the screen size
       windowWidth/=3;
       windowHeight/=3;
   }

   m_hWnd = CreateWindow("CPRTChildWindowClass", lpTitle, //APPTITLE, APPTITLE, //szWindowClass, szTitle, 
       WS_CHILDWINDOW | WS_VISIBLE,
       CW_USEDEFAULT, 
       CW_USEDEFAULT, 
       100, 
       100,
       parentHWnd, 
       NULL, 
       (HINSTANCE)GetWindowLongPtr(parentHWnd, GWLP_HINSTANCE), 
       NULL);

   if (!m_hWnd)
   {
      return FALSE;
   }

   ShowWindow(m_hWnd, nCmdShow);
   UpdateWindow(m_hWnd);

   CPUTOSServices* pServices = CPUTOSServices::GetOSServices();
   pServices->SethWnd(m_hWnd);

   return TRUE;
}
//-----------------------------------------------------------------------------
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;
}
Пример #10
0
// incoming resize event to be handled and translated
//-----------------------------------------------------------------------------
void CPUT_DX11::ResizeWindow(UINT width, UINT height)
{
    HRESULT hr;
    CPUTResult result;
    CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibraryDX11::GetAssetLibrary();

    // TODO: Making the back and depth buffers into CPUTRenderTargets should simplify this (CPUTRenderTarget* manages RTV, SRV, UAV, etc.)
    if( mpBackBuffer )         ((CPUTBufferDX11*)mpBackBuffer)->ReleaseBuffer();
    if( mpDepthBuffer )        ((CPUTBufferDX11*)mpDepthBuffer)->ReleaseBuffer();
    if( mpBackBufferTexture )  ((CPUTTextureDX11*)mpBackBufferTexture)->ReleaseTexture();
    if( mpDepthBufferTexture ) ((CPUTTextureDX11*)mpDepthBufferTexture)->ReleaseTexture();

    // Make sure we don't have any buffers bound.
    mpContext->ClearState();
    Present();
    mpContext->Flush();

    SAFE_RELEASE(mpBackBufferRTV);
    SAFE_RELEASE(mpBackBufferSRV);
    SAFE_RELEASE(mpBackBufferUAV);
    SAFE_RELEASE(mpDepthStencilSRV);

    CPUT::ResizeWindow( width, height );

    // Call the sample's clean up code if present.
    ReleaseSwapChain();

    // handle the internals of a resize
    int windowWidth, windowHeight;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    pServices->GetClientDimensions( &windowWidth, &windowHeight);

    // resize the swap chain
    hr = mpSwapChain->ResizeBuffers(mSwapChainBufferCount, windowWidth, windowHeight, mSwapChainFormat, 0);
    ASSERT( SUCCEEDED(hr), _L("Error resizing swap chain") );

    // re-create the render-target view
    ID3D11Texture2D *pSwapChainBuffer = NULL;
    hr = mpSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D), (LPVOID*) (&pSwapChainBuffer));
    ASSERT(SUCCEEDED(hr), _L(""));
    hr = mpD3dDevice->CreateRenderTargetView( pSwapChainBuffer, NULL, &mpBackBufferRTV);
    ASSERT(SUCCEEDED(hr), _L(""));
    hr = mpD3dDevice->CreateShaderResourceView( pSwapChainBuffer, NULL, &mpBackBufferSRV);
    ASSERT(SUCCEEDED(hr), _L(""));
#ifdef CREATE_SWAP_CHAIN_UAV
    // Not every DXGI format supports UAV.  So, create UAV only if sample chooses to do so.
    hr = mpD3dDevice->CreateUnorderedAccessView( pSwapChainBuffer, NULL, &mpBackBufferUAV);
    ASSERT(SUCCEEDED(hr), _L(""));
#endif
    // Add the back buffer to the asset library.  Create CPUTBuffer and a CPUTTexture forms and add them.
    if( mpBackBuffer )
    {
        ((CPUTBufferDX11*)mpBackBuffer)->SetBufferAndViews( NULL, mpBackBufferSRV, mpBackBufferUAV );
    }
    else
    {
        cString backBufferName = _L("$BackBuffer"); 
        mpBackBuffer  = new CPUTBufferDX11( backBufferName,  NULL, mpBackBufferUAV );
        pAssetLibrary->AddBuffer( backBufferName, mpBackBuffer );
    }
    if( mpBackBufferTexture )
    {
        ((CPUTTextureDX11*)mpBackBufferTexture)->SetTextureAndShaderResourceView( NULL, mpBackBufferSRV );
    }
    else
    {
        cString backBufferName = _L("$BackBuffer"); 
        mpBackBufferTexture  = new CPUTTextureDX11( backBufferName, NULL, mpBackBufferSRV );
        pAssetLibrary->AddTexture( backBufferName, mpBackBufferTexture );
    }

    // release the old depth buffer objects
    // release the temporary swap chain buffer
    SAFE_RELEASE(pSwapChainBuffer);
    SAFE_RELEASE(mpDepthStencilBuffer);
    SAFE_RELEASE(mpDepthStencilState);
    SAFE_RELEASE(mpDepthStencilView);

    result = CreateAndBindDepthBuffer(windowWidth, windowHeight);
    if(CPUTFAILED(result))
    {
        // depth buffer creation error
        ASSERT(0,_L(""));
    }

    if( mpDepthBuffer )
    {
        ((CPUTBufferDX11*)mpDepthBuffer)->SetBufferAndViews( NULL, mpDepthStencilSRV, NULL );
    }
    else
    {
        cString depthBufferName = _L("$DepthBuffer"); 
        mpDepthBuffer  = new CPUTBufferDX11( depthBufferName, NULL, mpDepthStencilSRV );
        pAssetLibrary->AddBuffer( depthBufferName, mpDepthBuffer );
    }
    if( mpDepthBufferTexture )
    {
        ((CPUTTextureDX11*)mpDepthBufferTexture)->SetTextureAndShaderResourceView( NULL, mpDepthStencilSRV );
    }
    else
    {
        cString DepthBufferName = _L("$DepthBuffer"); 
        mpDepthBufferTexture  = new CPUTTextureDX11( DepthBufferName, NULL, mpDepthStencilSRV );
        pAssetLibrary->AddTexture( DepthBufferName, mpDepthBufferTexture );
    }

    // Release our extra reference to each view.
    // if(mpBackBufferSRV)   mpBackBufferSRV->Release();
    // if(mpBackBufferUAV)   mpBackBufferUAV->Release();
    // if(mpDepthStencilSRV) mpDepthStencilSRV->Release();;

    // set the viewport
    D3D11_VIEWPORT vp;
    vp.Width = (FLOAT) windowWidth;
    vp.Height = (FLOAT)windowHeight;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    mpContext->RSSetViewports( 1, &vp );

    // trigger the GUI manager to resize
    CPUTGuiControllerDX11::GetController()->Resize();
}
Пример #11
0
// InitInstance
// Saves the windows instance handle, creates, and displays the main program
// window
//-----------------------------------------------------------------------------
BOOL CPUTWindowWin::InitInstance(int nCmdShow, int windowWidth, int windowHeight, int windowX, int windowY)
{
    // assure we have a valid hInstance
    ASSERT(NULL!=mhInst, _L(""));

   // zero sized windows means - you choose the size. :)
   if( (0==windowWidth) || (0==windowHeight) )
   {
       CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
       pServices->GetDesktopDimensions(&windowWidth, &windowHeight);

       // default window size 1280x720
       // but if screen is smaller than 1280x720, then pick 1/3 the screen size 
       // so that it doesn't appear off the edges
       if(1280>windowWidth)
       {
           windowWidth = (2*windowWidth)/3;
           windowHeight = (2*windowHeight)/3;
       }
       else
       {
        
        windowWidth=1280;
        windowHeight=720;
       }
   }

   // set up size structure
   RECT rc = { 0, 0, windowWidth, windowHeight };
   AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );

   // if x = -1, then let windows decide where to put it
   if(-1==windowX)
   {
       windowX = CW_USEDEFAULT;
   }

   // create the window
   mhWnd = CreateWindow(mAppTitle.c_str(), mAppTitle.c_str(),
       WS_OVERLAPPEDWINDOW,
       windowX, //CW_USEDEFAULT,
       windowY, //CW_USEDEFAULT,
       rc.right - rc.left,
       rc.bottom - rc.top,
       NULL,
       NULL,
       mhInst,
       NULL);

   if (!mhWnd)
   {
      return FALSE;
   }

   ShowWindow(mhWnd, nCmdShow);
   UpdateWindow(mhWnd);

   // initialize the OS services with the hWND so you can make
   // reference to this object
   CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
   pServices->SethWnd(mhWnd);

   return TRUE;
}
// Re-calculates all the positions of the controls based on their sizes
// to have a 'pretty' layout
//--------------------------------------------------------------------------------
void CPUTGuiController::RecalculateLayout()
{
    // if we have no valid panel, just return
    if(CPUT_CONTROL_ID_INVALID == mActiveControlPanelSlotID)
    {
        return;
    }

    // if we don't want the auto-layout feature, just return
    if(false == mbAutoLayout)
    {
        return;
    }

    // get window size
    CPUT_RECT windowRect;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices();
    pServices->GetClientDimensions(&windowRect.x, &windowRect.y, &windowRect.width, &windowRect.height);

    // Build columns of controls right to left
    int x,y;
    x=0; y=0;

    // walk list of controls, counting up their *heights*, until the
    // column is full.  While counting, keep track of the *widest*
    int width, height;
    const int GUI_WINDOW_PADDING = 5;

    int numberOfControls = (int) mControlPanelIDList[mActiveControlPanelSlotID]->mControlList.size();
    int indexStart=0;
    int indexEnd=0;
    int columnX = 0;
    int columnNumber = 1;
    while(indexEnd < numberOfControls)
    {
        int columnWidth=0;
        y=0;
        // figure out which controls belong in this column + column width
        while( indexEnd < numberOfControls )
        {
            if(mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[indexEnd]->IsVisible() &&
                mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[indexEnd]->IsAutoArranged())
            {
                mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[indexEnd]->GetDimensions(width, height);
                if( y + height + GUI_WINDOW_PADDING < (windowRect.height-2*GUI_WINDOW_PADDING))
                {
                    y = y + height + GUI_WINDOW_PADDING;
                    if(columnWidth < width)
                    {
                        columnWidth = width;
                    }
                    indexEnd++;
                }
                else
                {
                    // if the window is now so small it won't fit a whole control, just
                    // draw one anyway and it'll just have to be clipped
                    if(indexEnd == indexStart)
                    {
                        columnWidth = width;
                        indexEnd++;
                    }
                    break;
                }
            }
            else
            {
                indexEnd++;
            }
        }
        

        // ok, now re-position each control with x at widest, and y at proper height
        y=GUI_WINDOW_PADDING;
        for(int i=indexStart; i<indexEnd; i++)
        {
            if(mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[i]->IsVisible() &&
                mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[i]->IsAutoArranged())
            {
                mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[i]->GetDimensions(width, height);
                x = windowRect.width - columnX - columnWidth - (columnNumber*GUI_WINDOW_PADDING);
                mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[i]->SetPosition(x,y);

                y = y + height + GUI_WINDOW_PADDING;
            }
        }
        indexStart = indexEnd;
        columnX+=columnWidth;
        columnNumber++;
    }
        
    mRecalculateLayout = false;
}
//-----------------------------------------------
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;
}
// Draw - must be positioned after all the controls are defined
//--------------------------------------------------------------------------------
void CPUTGuiControllerDX11::Draw(ID3D11DeviceContext *pImmediateContext)
{
    HEAPCHECK;

    if( 0 != GetNumberOfControlsInPanel())
    {
        SetGUIDrawingState(pImmediateContext);
    }
    else
    {
        return;
    }

    ID3D11VertexShader *pVertexShader = mpGUIVertexShader->GetNativeVertexShader();
    ID3D11PixelShader  *pPixelShader  = mpGUIPixelShader->GetNativePixelShader();

    // if any of the controls have announced they are dirty, then rebuild the mirror buffer and rebind
    if(mUberBufferDirty)
    {
        
        // if a resize was flagged, do it now.  
        if(mRecalculateLayout)
        {
            RecalculateLayout();
        }


        // 'clear' the buffer by resetting the pointer to the head
        mUberBufferIndex = 0;
        mTextUberBufferIndex = 0;
        mFocusedControlBufferIndex = 0;
        mFocusedControlTextBufferIndex = 0;

        int ii=0;
        while(ii<GetNumberOfControlsInPanel())
        {
            CPUTControl *pControl = mControlPanelIDList[mActiveControlPanelSlotID]->mControlList[ii];

            // don't draw the focus control - draw it last so it stays on 'top'
            if(mpFocusControl != pControl)
            {
                switch(pControl->GetType())
                {
                case CPUT_BUTTON:
                    ((CPUTButton*)pControl)->DrawIntoBuffer(mpMirrorBuffer, &mUberBufferIndex, mUberBufferMax, mpTextMirrorBuffer, &mTextUberBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);                    
                    break;
                case CPUT_CHECKBOX:
                    ((CPUTCheckbox*)pControl)->DrawIntoBuffer(mpMirrorBuffer, &mUberBufferIndex, mUberBufferMax, mpTextMirrorBuffer, &mTextUberBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                    break;
                case CPUT_SLIDER:
                    ((CPUTSlider*)pControl)->DrawIntoBuffer(mpMirrorBuffer, &mUberBufferIndex, mUberBufferMax, mpTextMirrorBuffer, &mTextUberBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                    break;
                case CPUT_DROPDOWN:
                    ((CPUTDropdown*)pControl)->DrawIntoBuffer(mpMirrorBuffer, &mUberBufferIndex, mUberBufferMax, mpTextMirrorBuffer, &mTextUberBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                    break;

                case CPUT_STATIC:
                    ((CPUTText*)pControl)->DrawIntoBuffer(mpTextMirrorBuffer, &mTextUberBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                    break;
                }
            }
            ii++;
            HEAPCHECK
        }

        // do the 'focused' control last so it stays on top (i.e. dropdowns)
        if(mpFocusControl)
        {
            switch(mpFocusControl->GetType())
            {
            case CPUT_BUTTON:
                ((CPUTButton*)mpFocusControl)->DrawIntoBuffer(mpFocusedControlMirrorBuffer, &mFocusedControlBufferIndex, mUberBufferMax, mpFocusedControlTextMirrorBuffer, &mFocusedControlTextBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);                    
                break;
            case CPUT_CHECKBOX:
                ((CPUTCheckbox*)mpFocusControl)->DrawIntoBuffer(mpFocusedControlMirrorBuffer, &mFocusedControlBufferIndex, mUberBufferMax, mpFocusedControlTextMirrorBuffer, &mFocusedControlTextBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                break;
            case CPUT_SLIDER:
                ((CPUTSlider*)mpFocusControl)->DrawIntoBuffer(mpFocusedControlMirrorBuffer, &mFocusedControlBufferIndex, mUberBufferMax, mpFocusedControlTextMirrorBuffer, &mFocusedControlTextBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                break;
            case CPUT_DROPDOWN:
                ((CPUTDropdown*)mpFocusControl)->DrawIntoBuffer(mpFocusedControlMirrorBuffer, &mFocusedControlBufferIndex, mUberBufferMax, mpFocusedControlTextMirrorBuffer, &mFocusedControlTextBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                break;
            case CPUT_STATIC:
                ((CPUTText*)mpFocusControl)->DrawIntoBuffer(mpFocusedControlMirrorBuffer, &mFocusedControlTextBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);
                break;
            }
        }
        
                
        // update the uber-buffers with the control graphics
        UpdateUberBuffers(pImmediateContext);

        // Clear dirty flag on uberbuffer
        mUberBufferDirty = false;

    }
    HEAPCHECK



    // calculate the fps
    double elapsed = mpFPSTimer->GetElapsedTime();
    double fps = 1.0 / elapsed;
    mLastFPS = (float) fps;

	mFPSAvg[mFPSInst] = (float) fps;
	mFPSInst++;
	if(mFPSInst == AVG_FRAMES)
		mFPSInst = 0;

	float total = 0.0f;
	for(int i = 0; i < AVG_FRAMES; i++)
	{
		total += mFPSAvg[i];
	}

    int windowWidth, windowHeight;
    CPUTOSServices *pServices = CPUTOSServices::GetOSServices( );
    pServices->GetClientDimensions( &windowWidth, &windowHeight );

    // if we're drawing the FPS counter - update that
    // We do this independently of uber-buffer updates since we'll have FPS updates every frame,
    // but likely not have control updates every frame
    if(mbDrawFPS)
    {
        // calculate the time elapsed since last frame
        bool UberBufferWasDirty = mUberBufferDirty;

        cString Data;
        {
            wchar_t wcstring[CPUT_MAX_STRING_LENGTH];
            float avgFps = total/(float)AVG_FRAMES;
            swprintf_s(&wcstring[0], CPUT_MAX_STRING_LENGTH, _L("Window res: %d x %d, AVG FPS:%.2f \t(FPS:%.2f)  "), windowWidth, windowHeight, avgFps, fps);
            Data=wcstring;
        }
		// build the FPS string
        cString FPS = Data;
        mpFPSCounter->SetText(FPS); 

        // 'draw' the string into the buffer
        mFPSBufferIndex = 0;
        mpFPSCounter->DrawIntoBuffer(mpFPSMirrorBuffer, &mFPSBufferIndex, CPUT_GUI_BUFFER_STRING_SIZE);

        // update the DirectX vertex buffer
        ASSERT(CPUT_GUI_BUFFER_STRING_SIZE > mFocusedControlTextBufferIndex, _L("CPUT GUI: Too many strings for default-sized uber-buffer.  Increase CPUT_GUI_BUFFER_STRING_SIZE"));
        pImmediateContext->UpdateSubresource(mpFPSDirectXBuffer, 0, NULL, mpFPSMirrorBuffer, mFPSBufferIndex*sizeof(CPUTGUIVertex), 0);
        
        // start next frame timer
        mpFPSTimer->StartTimer();
        if(false == UberBufferWasDirty)
        {
            mUberBufferDirty = false;
        }
    }


    // set up orthographic display
    GUIConstantBufferVS ConstantBufferMatrices;
    float znear = 0.1f;
    float zfar = 100.0f;
	DirectX::XMMATRIX m;

    m = DirectX::XMMatrixOrthographicOffCenterLH(0, (float)windowWidth, (float)windowHeight, 0, znear, zfar);
    ConstantBufferMatrices.Projection = XMMatrixTranspose( m );

    // set the vertex shader
    pImmediateContext->VSSetShader( pVertexShader, NULL, 0 );
    UINT VertexStride = sizeof(CPUTGUIVertex);
    UINT VertexOffset = 0;
    pImmediateContext->IASetVertexBuffers( 0, 1, &mpUberBuffer, &VertexStride, &VertexOffset );

    m = DirectX::XMMatrixIdentity();
    ConstantBufferMatrices.Model = XMMatrixTranspose( m );
    pImmediateContext->UpdateSubresource( mpConstantBufferVS, 0, NULL, &ConstantBufferMatrices, 0, 0 );
    pImmediateContext->VSSetConstantBuffers( 0, 1, &mpConstantBufferVS );

    // -- draw the normal controls --    
    // draw the control graphics
    pImmediateContext->PSSetShader( pPixelShader, NULL, 0 );
    pImmediateContext->PSSetShaderResources( 0, 1, &mpControlTextureAtlasView );    
    pImmediateContext->Draw(mUberBufferIndex,0);

    // draw the control's text
    pImmediateContext->PSSetShaderResources( 0, 1, &mpTextTextureAtlasView );
    pImmediateContext->IASetVertexBuffers( 0, 1, &mpTextUberBuffer, &VertexStride, &VertexOffset );
    // draw the text uber-buffer
    pImmediateContext->Draw(mTextUberBufferIndex,0);

    // draw the FPS counter
    if(mbDrawFPS)
    {
        pImmediateContext->IASetVertexBuffers( 0, 1, &mpFPSDirectXBuffer, &VertexStride, &VertexOffset );
        pImmediateContext->Draw(mFPSBufferIndex, 0);
    }
    
    // -- draw the focused control --
    // Draw the focused control's graphics
    pImmediateContext->PSSetShader( pPixelShader, NULL, 0 );
    pImmediateContext->PSSetShaderResources( 0, 1, &mpControlTextureAtlasView );
    pImmediateContext->IASetVertexBuffers( 0, 1, &mpFocusedControlBuffer, &VertexStride, &VertexOffset );
    // draw the uber-buffer
    pImmediateContext->Draw(mFocusedControlBufferIndex,0);


    // Draw the focused control's text
    pImmediateContext->PSSetShaderResources( 0, 1, &mpTextTextureAtlasView );
    pImmediateContext->IASetVertexBuffers( 0, 1, &mpFocusedControlTextBuffer, &VertexStride, &VertexOffset );
    // draw the text uber-buffer
    pImmediateContext->Draw(mFocusedControlTextBufferIndex,0);


    // restore the drawing state
    ClearGUIDrawingState(pImmediateContext);
    HEAPCHECK;
}