//-----------------------------------------------------------------------------
CPUTResult CPUTTextureDX11::CreateNativeTexture(
    ID3D11Device *pD3dDevice,
    const cString &fileName,
    ID3D11ShaderResourceView **ppShaderResourceView,
    ID3D11Resource **ppTexture,
    bool ForceLoadAsSRGB)
{
    HRESULT hr;

    hr = DirectX::CreateDDSTextureFromFileEx(
        pD3dDevice,
        fileName.c_str(),
        0,//maxsize
        D3D11_USAGE_DEFAULT,
        D3D11_BIND_SHADER_RESOURCE,
        0,
        0,
        ForceLoadAsSRGB,
        ppTexture,
        ppShaderResourceView);
	if( FAILED( hr ) )
	{
		ASSERT( false, _L("Failed to load texture: ") + fileName )
		return CPUT_TEXTURE_LOAD_ERROR;
	}

    CPUTSetDebugName( *ppTexture, fileName );
    CPUTSetDebugName( *ppShaderResourceView, fileName );

    return CPUT_SUCCESS;
}
//-----------------------------------------------
HRESULT CPUTSprite::CreateSprite(
    float          spriteX,
    float          spriteY,
    float          spriteWidth,
    float          spriteHeight,
    const cString &spriteMaterialName
)
{
    HRESULT result;

    // Create resources so we can draw a sprite using the render target as a texture
    mpMaterial = CPUTAssetLibrary::GetAssetLibrary()->GetMaterial( spriteMaterialName, false );

    // Define the input layout
    D3D11_INPUT_ELEMENT_DESC pLayout[] =
    {
        { "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 },
        {0}
    };
    CPUTVertexShaderDX11 *pVertexShader = ((CPUTMaterialDX11*)mpMaterial)->GetVertexShader();
    ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice();
    CPUTInputLayoutCacheDX11::GetInputLayoutCache()->GetLayout( pD3dDevice, pLayout, pVertexShader, &mpInputLayout);

    // ***************************************************
    // Create Vertex Buffers
    // ***************************************************
    D3D11_BUFFER_DESC bd;
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof(SpriteVertex) * 6; // 2 tris, 3 verts each vertices
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    bd.MiscFlags = 0;

    const float top    = -spriteY; //-1.0f;
    const float bottom = -spriteY - spriteHeight; // 1.0f;
    const float left   =  spriteX; //-1.0f;
    const float right  =  spriteX + spriteWidth; // 1.0f;
    SpriteVertex pVertices[] = {
        {  left,    top, 1.0f,   0.0f, 0.0f },
        { right,    top, 1.0f,   1.0f, 0.0f },
        {  left, bottom, 1.0f,   0.0f, 1.0f },

        { right,    top, 1.0f,   1.0f, 0.0f },
        { right, bottom, 1.0f,   1.0f, 1.0f },
        {  left, bottom, 1.0f,   0.0f, 1.0f }
    };
    D3D11_SUBRESOURCE_DATA initialData;
    initialData.pSysMem = pVertices;
    initialData.SysMemPitch = sizeof( SpriteVertex );
    initialData.SysMemSlicePitch = 0;

    result = pD3dDevice->CreateBuffer( &bd, &initialData, &mpVertexBuffer );
    ASSERT( SUCCEEDED(result), _L("Failed creating render target debug-sprite vertex buffer") );
    CPUTSetDebugName( mpVertexBuffer, _L("CPUTSprite vertex buffer") );

    return S_OK;
} // CPUTSprite::CreateSprite()
void CPUTGUIElement::SetText(cString string)
{
    DEBUG_PRINT(_L("GUIElement SetText: %s"), string.c_str());
    mText = string;
    if(mpFont && mpTextMaterial)
    {
        DEBUG_PRINT(_L("\t have font and material"));
        if(!mpTextMesh)
        {
#ifdef CPUT_FOR_DX11
            mpTextMesh = new CPUTMeshDX11();
#else
            mpTextMesh = new CPUTMeshOGL();
#endif
        }
        unsigned int numCharacters = (unsigned int) string.size();
        unsigned int numVertices = numCharacters * 6;
        CPUTGUIVertex* pVB = new CPUTGUIVertex[numVertices];

        CPUTBufferElementInfo pGUIVertex[3] = {
            { "POSITION", 0, 0, CPUT_F32, 3, 3*sizeof(float), 0 },            
            { "TEXCOORD", 0, 1, CPUT_F32, 2, 2*sizeof(float), 3*sizeof(float)},
            { "COLOR",    0, 2, CPUT_F32, 4, 4*sizeof(float), 5*sizeof(float)},
        };
        mpFont->LayoutText(NULL, &mTextWidth, &mTextHeight, mText, 0, 0);
        mTextX = (mWidth-mTextWidth)/2;
        mTextY = (mHeight-mTextHeight)/2;
        mpFont->LayoutText(pVB, &mTextWidth, &mTextHeight, mText, 0, 0);
        mpTextMesh->CreateNativeResources(NULL, 1, 3, pGUIVertex, numVertices, pVB, NULL, 0, NULL);
        
#ifdef CPUT_FOR_DX11
        mpTextMesh->SetMeshTopology(CPUT_TOPOLOGY_INDEXED_TRIANGLE_LIST);
        
        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 },
            { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        };
        UINT numElements = ARRAYSIZE( layout );
        ID3DBlob* pBlob = ((CPUTMaterialEffectDX11*)mpTextMaterial->GetMaterialEffects()[0])->GetVertexShader()->GetBlob();
        
        CPUT_DX11::GetDevice()->CreateInputLayout( layout, numElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), &mpVertexLayout );
        CPUTSetDebugName( mpVertexLayout, "CPUT GUI InputLayout object");
#else
#endif
        SAFE_DELETE_ARRAY(pVB);
    }
}
Beispiel #4
0
//-----------------------------------------------------------------------------
void CPUTModelDX11::CreateModelConstantBuffer()
{
    CPUTAssetLibraryDX11 *pAssetLibrary = (CPUTAssetLibraryDX11*)CPUTAssetLibrary::GetAssetLibrary();

    // Create the model constant buffer.
    HRESULT hr;
    D3D11_BUFFER_DESC bd = {0};
    bd.ByteWidth = sizeof(CPUTModelConstantBuffer);
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    hr = (CPUT_DX11::GetDevice())->CreateBuffer( &bd, NULL, &mpModelConstantBuffer );
    ASSERT( !FAILED( hr ), _L("Error creating constant buffer.") );
    CPUTSetDebugName( mpModelConstantBuffer, _L("Model Constant buffer") );
    cString name = _L("$cbPerModelValues");
    CPUTBufferDX11 *pBuffer = new CPUTBufferDX11(name, mpModelConstantBuffer);
    pAssetLibrary->AddConstantBuffer( name, pBuffer );
    pBuffer->Release(); // We're done with it.  We added it to the library.  Release our reference.
}
// find existing, or create new, ID3D11InputLayout layout
//-----------------------------------------------------------------------------
CPUTResult CPUTInputLayoutCacheDX11::GetLayout(
    ID3D11Device *pDevice,
    D3D11_INPUT_ELEMENT_DESC *pDXLayout,
    CPUTVertexShaderDX11 *pVertexShader,
    ID3D11InputLayout **ppInputLayout
){
    // Generate the vertex layout pattern portion of the key
    cString layoutKey = GenerateLayoutKey(pDXLayout);

    // Append the vertex shader pointer to the key for layout<->vertex shader relationship
    cString address = ptoc(pVertexShader);
    layoutKey += address;

    // Do we already have one like this?
    if( mLayoutList[layoutKey] )
    {
        *ppInputLayout = mLayoutList[layoutKey];
        (*ppInputLayout)->AddRef();
        return CPUT_SUCCESS;
    }
    // Not found, create a new ID3D11InputLayout object

    // How many elements are in the input layout?
    int numInputLayoutElements=0;
    while(NULL != pDXLayout[numInputLayoutElements].SemanticName)
    {
        numInputLayoutElements++;
    }
    // Create the input layout
    HRESULT hr;
    ID3DBlob *pBlob = pVertexShader->GetBlob();
    hr = pDevice->CreateInputLayout( pDXLayout, numInputLayoutElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), ppInputLayout );
    ASSERT( SUCCEEDED(hr), _L("Error creating input layout.") );
    CPUTSetDebugName( *ppInputLayout, _L("CPUTInputLayoutCacheDX11::GetLayout()") );

    // Store this layout object in our map
    mLayoutList[layoutKey] = *ppInputLayout;

    // Addref for storing it in our map as well as returning it (count should be = 2 at this point)
    (*ppInputLayout)->AddRef();

    return CPUT_SUCCESS;
}
Beispiel #6
0
// Default creation routine for making the back/stencil buffers
//-----------------------------------------------------------------------------
CPUTResult CPUT_DX11::CreateContext()
{
    HRESULT hr;
    CPUTResult result;
    RECT rc;
    HWND hWnd = mpWindow->GetHWnd();

    GetClientRect( hWnd, &rc );
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    // Create a render target view
    ID3D11Texture2D *pBackBuffer = NULL;
    hr = mpSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
    ASSERT( SUCCEEDED(hr), _L("Failed getting back buffer.") );

    hr = mpD3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &mpBackBufferRTV );
    pBackBuffer->Release();
    ASSERT( SUCCEEDED(hr), _L("Failed creating render target view.") );
    CPUTSetDebugName( mpBackBufferRTV, _L("BackBufferView") );

    // create depth/stencil buffer
    result = CreateAndBindDepthBuffer(width, height);
    ASSERT( SUCCEEDED(hr), _L("Failed creating and binding depth buffer.") );

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

    return CPUT_SUCCESS;
}
Beispiel #7
0
CPUTResult CPUTTextureDX11::CreateNativeTexture(
    ID3D11Device *pD3dDevice,
    const cString &fileName,
    ID3D11ShaderResourceView **ppShaderResourceView,
    ID3D11Resource **ppTexture,
    bool ForceLoadAsSRGB
){
    CPUTResult result;
    HRESULT hr;

    // Set up loading structure
    //
    // Indicate all texture parameters should come from the file
    D3DX11_IMAGE_LOAD_INFO LoadInfo;
    ZeroMemory(&LoadInfo, sizeof(D3DX11_IMAGE_LOAD_INFO));
    LoadInfo.Width          = D3DX11_FROM_FILE;
    LoadInfo.Height         = D3DX11_FROM_FILE;
    LoadInfo.Depth          = D3DX11_FROM_FILE;
    LoadInfo.FirstMipLevel  = D3DX11_FROM_FILE;
    LoadInfo.MipLevels      = D3DX11_FROM_FILE;
    // LoadInfo.Usage          = D3D11_USAGE_IMMUTABLE; // TODO: maintain a "mappable" flag?  Set immutable if not mappable?
    LoadInfo.Usage          = D3D11_USAGE_DEFAULT;
    LoadInfo.BindFlags      = D3D11_BIND_SHADER_RESOURCE;
    LoadInfo.CpuAccessFlags = 0;
    LoadInfo.MiscFlags      = 0;
    LoadInfo.MipFilter      = D3DX11_FROM_FILE;
    LoadInfo.pSrcInfo       = NULL;
    LoadInfo.Format         = (DXGI_FORMAT) D3DX11_FROM_FILE;
    LoadInfo.Filter         = D3DX11_FILTER_NONE;

    // if we're 'forcing' load of sRGB data, we need to verify image is sRGB
    // or determine image format that best matches the non-sRGB source format in hopes that the conversion will be faster
    // and data preserved
    if(true == ForceLoadAsSRGB)
    {
        // get the source image info
        D3DX11_IMAGE_INFO SrcInfo;
        hr = D3DX11GetImageInfoFromFile(fileName.c_str(), NULL, &SrcInfo, NULL);
        ASSERT( SUCCEEDED(hr), _L(" - Error loading texture '")+fileName+_L("'.") );

        // find a closest equivalent sRGB format
        result = GetSRGBEquivalent(SrcInfo.Format, LoadInfo.Format);
        ASSERT( CPUTSUCCESS(result), _L("Error loading texture '")+fileName+_L("'.  It is specified this texture must load as sRGB, but the source image is in a format that cannot be converted to sRGB.\n") );

        // set filtering mode to interpret 'in'-coming data as sRGB, and storing it 'out' on an sRGB surface
        //
        // As it stands, we don't have any tools that support sRGB output in DXT compressed textures.
        // If we later support a format that does provide sRGB, then the filter 'in' flag will need to be removed
        LoadInfo.Filter = D3DX11_FILTER_NONE | D3DX11_FILTER_SRGB_IN | D3DX11_FILTER_SRGB_OUT;
#if 0
        // DWM: TODO:  We want to catch the cases where the loader needs to do work.
        // This happens if the texture's pixel format isn't supported by DXGI.
        // TODO: how to determine?

        // if a runtime conversion must happen report a performance warning error.
        // Note: choosing not to assert here, as this will be a common issue.
        if( SrcInfo.Format != LoadInfo.Format)
        {
            cString dxgiName = GetDXGIFormatString(SrcInfo.Format);
            cString errorString = _T(__FUNCTION__);
            errorString += _L("- PERFORMANCE WARNING: '") + fileName
            +_L("' has an image format ")+dxgiName
            +_L(" but must be run-time converted to ")+GetDXGIFormatString(LoadInfo.Format)
            +_L(" based on requested sRGB target buffer.\n");
            TRACE( errorString.c_str() );
        }
#endif
    }
    //hr = D3DX11CreateTextureFromFile( pD3dDevice, fileName.c_str(), &LoadInfo, NULL, ppTexture, NULL );
    hr = MyCreateTextureFromFile( pD3dDevice, fileName.c_str(), &LoadInfo, NULL, ppTexture, NULL );
    ASSERT( SUCCEEDED(hr), _L("Failed to load texture: ") + fileName );
    CPUTSetDebugName( *ppTexture, fileName );

    hr = pD3dDevice->CreateShaderResourceView( *ppTexture, NULL, ppShaderResourceView );
    ASSERT( SUCCEEDED(hr), _L("Failed to create texture shader resource view.") );
    CPUTSetDebugName( *ppShaderResourceView, fileName );

    return CPUT_SUCCESS;
}
// Create the DX vertex/index buffers and D3D11_INPUT_ELEMENT_DESC
//-----------------------------------------------------------------------------
CPUTResult CPUTMeshDX11::CreateNativeResources(
    CPUTModel              *pModel,
    UINT                    meshIdx,
    int                     vertexElementCount,
    CPUTBufferElementInfo  *pVertexDataInfo,
    UINT                    vertexCount,
    void                   *pVertexData,
    CPUTBufferElementInfo  *pIndexDataInfo,
    UINT                    indexCount,
    void                   *pIndexData
){

    CPUTResult result = CPUT_SUCCESS;
    HRESULT hr;

    ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice();

    // Release the layout, offset, stride, and vertex buffer structure objects
    ClearAllObjects();

    // allocate the layout, offset, stride, and vertex buffer structure objects
    mpLayoutDescription = new D3D11_INPUT_ELEMENT_DESC[vertexElementCount+1];

    // Create the index buffer
    D3D11_SUBRESOURCE_DATA resourceData;
    if(NULL!=pIndexData)
    {
        mIndexCount = indexCount;

        // set the data format info
        ZeroMemory( &mIndexBufferDesc, sizeof(mIndexBufferDesc) );
        mIndexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
        mIndexBufferDesc.ByteWidth = mIndexCount * pIndexDataInfo->mElementSizeInBytes;
        mIndexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
        mIndexBufferDesc.CPUAccessFlags = 0;  // default to no cpu access for speed

        // create the buffer
        ZeroMemory( &resourceData, sizeof(resourceData) );
        resourceData.pSysMem = pIndexData;
        hr = pD3dDevice->CreateBuffer( &mIndexBufferDesc, &resourceData, &mpIndexBuffer );
        ASSERT(!FAILED(hr), _L("Failed creating index buffer") );
        CPUTSetDebugName( mpIndexBuffer, _L("Index buffer") );

        // set the DX index buffer format
        mIndexBufferFormat = ConvertToDirectXFormat(pIndexDataInfo->mElementType, pIndexDataInfo->mElementComponentCount);
    }

    // Create the vertex buffer
    mVertexCount = vertexCount;
    ZeroMemory( &mVertexBufferDesc, sizeof(mVertexBufferDesc) );
    mVertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    mVertexStride = pVertexDataInfo[vertexElementCount-1].mOffset + pVertexDataInfo[vertexElementCount-1].mElementSizeInBytes; // size in bytes of a single vertex block
    mVertexBufferDesc.ByteWidth = mVertexCount * mVertexStride; // size in bytes of entire buffer
    mVertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    mVertexBufferDesc.CPUAccessFlags = 0;  // default to no cpu access for speed

    ZeroMemory( &resourceData, sizeof(resourceData) );
    resourceData.pSysMem = pVertexData;
    if (pVertexData) {
        hr = pD3dDevice->CreateBuffer( &mVertexBufferDesc, &resourceData, &mpVertexBuffer );
    } else {
        hr = pD3dDevice->CreateBuffer( &mVertexBufferDesc, NULL, &mpVertexBuffer );
    }
    ASSERT( !FAILED(hr), _L("Failed creating vertex buffer") );
    CPUTSetDebugName( mpVertexBuffer, _L("Vertex buffer") );

    // create the buffer for the shader resource view
    D3D11_BUFFER_DESC desc;
    ZeroMemory( &desc, sizeof(desc) );
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.ByteWidth           = mVertexCount * mVertexStride; // size in bytes of entire buffer
    desc.BindFlags           = D3D11_BIND_SHADER_RESOURCE;
    desc.CPUAccessFlags      = 0;
    desc.MiscFlags           = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
    desc.StructureByteStride = mVertexStride;

    if (pVertexData) {
        hr = pD3dDevice->CreateBuffer( &desc, &resourceData, &mpVertexBufferForSRVDX );
    } else {
        hr = pD3dDevice->CreateBuffer( &desc, NULL, &mpVertexBufferForSRVDX );
    }
    ASSERT( !FAILED(hr), _L("Failed creating vertex buffer for SRV") );
    CPUTSetDebugName( mpVertexBuffer, _L("Vertex buffer for SRV") );

    // Create the shader resource view
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;  
    ZeroMemory( &srvDesc, sizeof(srvDesc) );  
    srvDesc.Format = DXGI_FORMAT_UNKNOWN;  
    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;  
    srvDesc.Buffer.ElementOffset = 0;  
    srvDesc.Buffer.NumElements = mVertexCount;

    hr = pD3dDevice->CreateShaderResourceView( mpVertexBufferForSRVDX, &srvDesc, &mpVertexView );
    ASSERT( !FAILED(hr), _L("Failed creating vertex buffer SRV") );

    cString name = _L("@VertexBuffer") + ptoc(pModel) + itoc(meshIdx);
    mpVertexBufferForSRV = new CPUTBufferDX11( name, mpVertexBufferForSRVDX, mpVertexView );
    CPUTAssetLibrary::GetAssetLibrary()->AddBuffer( name, _L(""), _L(""), mpVertexBufferForSRV );

    // build the layout object
    int currentByteOffset=0;
    mNumberOfInputLayoutElements = vertexElementCount;
    for(int ii=0; ii<vertexElementCount; ii++)
    {
        mpLayoutDescription[ii].SemanticName  = pVertexDataInfo[ii].mpSemanticName; // string name that matches
        mpLayoutDescription[ii].SemanticIndex = pVertexDataInfo[ii].mSemanticIndex; // if we have more than one
        mpLayoutDescription[ii].Format = ConvertToDirectXFormat(pVertexDataInfo[ii].mElementType, pVertexDataInfo[ii].mElementComponentCount);
        mpLayoutDescription[ii].InputSlot = 0; // TODO: We support only a single stream now.  Support multiple streams.
        mpLayoutDescription[ii].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
        mpLayoutDescription[ii].InstanceDataStepRate = 0;
        mpLayoutDescription[ii].AlignedByteOffset = currentByteOffset;
        currentByteOffset += pVertexDataInfo[ii].mElementSizeInBytes;
    }
    // set the last 'dummy' element to null.  Not sure if this is required, as we also pass in count when using this list.
    memset( &mpLayoutDescription[vertexElementCount], 0, sizeof(D3D11_INPUT_ELEMENT_DESC) );

    return result;
}
//-----------------------------------------------------------------------------
D3D11_MAPPED_SUBRESOURCE CPUTMeshDX11::Map(
    UINT                   count,
    ID3D11Buffer          *pBuffer,
    D3D11_BUFFER_DESC     &bufferDesc,
    ID3D11Buffer         **pStagingBuffer,
    eCPUTMapType          *pMappedType,
    CPUTRenderParameters  &params,
    eCPUTMapType           type,
    bool                   wait
)
{
    // Mapping for DISCARD requires dynamic buffer.  Create dynamic copy?
    // Could easily provide input flag.  But, where would we specify? Don't like specifying in the .set file
    // Because mapping is something the application wants to do - it isn't inherent in the data.
    // Could do Clone() and pass dynamic flag to that.
    // But, then we have two.  Could always delete the other.
    // Could support programatic flag - apply to all loaded models in the .set
    // Could support programatic flag on model.  Load model first, then load set.
    // For now, simply support CopyResource mechanism.
    HRESULT hr;
    ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice();
    CPUTRenderParametersDX *pParamsDX11 = (CPUTRenderParametersDX*)&params;
    ID3D11DeviceContext *pContext = pParamsDX11->mpContext;

    if( !*pStagingBuffer )
    {
        D3D11_BUFFER_DESC desc = bufferDesc;
        // First time.  Create the staging resource
        desc.Usage = D3D11_USAGE_STAGING;
        switch( type )
        {
        case CPUT_MAP_READ:
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
            desc.BindFlags = 0;
            break;
        case CPUT_MAP_READ_WRITE:
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
            desc.BindFlags = 0;
            break;
        case CPUT_MAP_WRITE:
        case CPUT_MAP_WRITE_DISCARD:
        case CPUT_MAP_NO_OVERWRITE:
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            desc.BindFlags = 0;
            break;
        };
        hr = pD3dDevice->CreateBuffer( &desc, NULL, pStagingBuffer );
        ASSERT( SUCCEEDED(hr), _L("Failed to create staging buffer") );
        CPUTSetDebugName( *pStagingBuffer, _L("Mesh Staging buffer") );
    }
    else
    {
        ASSERT( *pMappedType == type, _L("Mapping with a different CPU access than creation parameter.") );
    }

    D3D11_MAPPED_SUBRESOURCE info;
    switch( type )
    {
    case CPUT_MAP_READ:
    case CPUT_MAP_READ_WRITE:
        // TODO: Copying and immediately mapping probably introduces a stall.
        // Expose the copy externally?
        // TODO: copy only if vb has changed?
        // Copy only first time?
        // Copy the GPU version before we read from it.
        pContext->CopyResource( *pStagingBuffer, pBuffer );
        break;
    };
    hr = pContext->Map( *pStagingBuffer, wait ? 0 : D3D11_MAP_FLAG_DO_NOT_WAIT, (D3D11_MAP)type, 0, &info );
    *pMappedType = type;
    return info;
} // CPUTMeshDX11::Map()
Beispiel #10
0
// Create the depth buffer
//-----------------------------------------------------------------------------
CPUTResult CPUT_DX11::CreateAndBindDepthBuffer(int width, int height)
{
    HRESULT hr;

    // Clamp to minimum size of 1x1 pixel
    width  = max( width, 1 );
    height = max( height, 1 );

    // ---- DEPTH BUFFER ---
    // 1. Initialize the description of the depth buffer.
    D3D11_TEXTURE2D_DESC depthBufferDesc;
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));

    // Set up the description of the depth buffer.
    depthBufferDesc.Width = width;
    depthBufferDesc.Height = height;
    depthBufferDesc.MipLevels = 1;
    depthBufferDesc.ArraySize = 1;
    depthBufferDesc.Format = DXGI_FORMAT_R32_TYPELESS;
    depthBufferDesc.SampleDesc.Count = 1;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

    // Create the texture for the depth buffer using the filled out description.
    hr = mpD3dDevice->CreateTexture2D(&depthBufferDesc, NULL, &mpDepthStencilBuffer);
    ASSERT( SUCCEEDED(hr), _L("Failed to create texture.") );
    CPUTSetDebugName( mpDepthStencilBuffer, _L("DepthBufferTexture") );

    // 2. Initialize the description of the stencil state.
    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;    
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));

    // Set up the description of the stencil state.
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL;

    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;

    // Stencil operations if pixel is front-facing.
    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Stencil operations if pixel is back-facing.
    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // Create the depth stencil state.
    hr = mpD3dDevice->CreateDepthStencilState(&depthStencilDesc, &mpDepthStencilState);
    ASSERT( SUCCEEDED(hr), _L("Failed to create depth-stencil state.") );
    mpContext->OMSetDepthStencilState(mpDepthStencilState, 1);

    // Create shader resource view
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    ZeroMemory(&srvDesc, sizeof(srvDesc));
    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    srvDesc.Texture2D.MipLevels = 1;
    srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
    hr = mpD3dDevice->CreateShaderResourceView(mpDepthStencilBuffer, &srvDesc, &mpDepthStencilSRV);
    ASSERT( SUCCEEDED(hr), _L("Failed to create depth-stencil SRV.") );
    CPUTSetDebugName( mpDepthStencilSRV, _L("DepthStencilSRV") );

    // Create the depth stencil view.
    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
    depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;

    hr = mpD3dDevice->CreateDepthStencilView(mpDepthStencilBuffer, &depthStencilViewDesc, &mpDepthStencilView);
    ASSERT( SUCCEEDED(hr), _L("Failed to create depth-stencil view.") );
    CPUTSetDebugName( mpDepthStencilView, _L("DepthStencilView") );

    // Bind the render target view and depth stencil buffer to the output render pipeline.
    mpContext->OMSetRenderTargets(1, &mpBackBufferRTV, mpDepthStencilView);

    CPUTRenderTargetColor::SetActiveRenderTargetView( mpBackBufferRTV );
    CPUTRenderTargetDepth::SetActiveDepthStencilView( mpDepthStencilView );

    return CPUT_SUCCESS;
}
Beispiel #11
0
// Create a DX11 context
//-----------------------------------------------------------------------------
CPUTResult CPUT_DX11::CreateDXContext(CPUTContextCreation ContextParams )
{

    HRESULT hr = S_OK;
    CPUTResult result = CPUT_SUCCESS;

    // window params
    RECT rc;
    HWND hWnd = mpWindow->GetHWnd();
    GetClientRect( hWnd, &rc );
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    // set up DirectX creation parameters
    mdriverType = D3D_DRIVER_TYPE_NULL;
    mfeatureLevel = D3D_FEATURE_LEVEL_11_0;
    mpD3dDevice = NULL;
    mpContext = NULL;
    mpSwapChain = NULL;
    mSwapChainBufferCount = ContextParams.swapChainBufferCount;
    mpBackBufferRTV = NULL;
    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_DRIVER_TYPE driverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT numDriverTypes = ARRAYSIZE( driverTypes );

    // SRV's (shader resource views) require Structured Buffer
    // usage (D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) which was 
    // introduced in shader model 5 (directx 11.0)
    //
    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0
    };
    UINT numFeatureLevels = ARRAYSIZE( featureLevels );

    // swap chain information
    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory( &sd, sizeof( sd ) );
    sd.BufferCount = mSwapChainBufferCount;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;

    mSwapChainFormat = ContextParams.swapChainFormat;
    sd.BufferDesc.Format = ContextParams.swapChainFormat;
    sd.BufferDesc.RefreshRate.Numerator = ContextParams.refreshRate;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = ContextParams.swapChainUsage;
    sd.OutputWindow = hWnd;
    sd.SampleDesc.Count = 1;  // Number of MSAA samples
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;
    sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    // set the vsync parameter
    if(0 != ContextParams.refreshRate)
    {
        mSyncInterval = 1;
    } else {
        mSyncInterval = 0;
    }

    // walk devices and create device and swap chain on best matching piece of hardware
    bool functionalityTestPassed = false;
    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
    {
        mdriverType = driverTypes[driverTypeIndex];
        hr = D3D11CreateDeviceAndSwapChain(
            NULL,
            mdriverType,
            NULL,
            createDeviceFlags,
            featureLevels,
            numFeatureLevels,
            D3D11_SDK_VERSION,
            &sd,
            &mpSwapChain,
            &mpD3dDevice,
            &mfeatureLevel,
            &mpContext
        );
        if( SUCCEEDED( hr ) )
        {
            functionalityTestPassed = TestContextForRequiredFeatures();
            if(true == functionalityTestPassed)
            {
                break;
            }
            else
            {
                // context was created, but failed to have required features
                // release and destroy this context and created resources
                SAFE_RELEASE(mpSwapChain);
                SAFE_RELEASE(mpContext);
                SAFE_RELEASE(mpD3dDevice);
            }
        }
    }
    ASSERT( (SUCCEEDED(hr) && (true==functionalityTestPassed)), _L("Failed creating device and swap chain.") );
    if(!SUCCEEDED(hr) || !functionalityTestPassed)
    {
        CPUTOSServices::GetOSServices()->OpenMessageBox(_L("Required DirectX hardware support not present"), _L("Your system does not support the DirectX feature levels required for this sample."));
        exit(1); // exit app directly
    }
   
    // If the WARP or Reference rasterizer is being used, the performance is probably terrible.
    // we throw up a dialog right after drawing the loading screen in CPUTCreateWindowAndContext
    // warning about that perf problem

    // call the DeviceCreated callback/backbuffer/etc creation
    result = CreateContext();

    CPUTRenderStateBlock *pBlock = new CPUTRenderStateBlockDX11();
    pBlock->CreateNativeResources();
    CPUTRenderStateBlock::SetDefaultRenderStateBlock( pBlock );

    // Create the per-frame constant buffer.
    D3D11_BUFFER_DESC bd = {0};
    bd.ByteWidth = sizeof(CPUTFrameConstantBuffer);
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    ID3D11Buffer *pPerFrameConstantBuffer;
    hr = (CPUT_DX11::GetDevice())->CreateBuffer( &bd, NULL, &pPerFrameConstantBuffer );
    ASSERT( !FAILED( hr ), _L("Error creating constant buffer.") );
    CPUTSetDebugName( pPerFrameConstantBuffer, _L("Per-Frame Constant buffer") );
    cString name = _L("$cbPerFrameValues");
    mpPerFrameConstantBuffer = new CPUTBufferDX11( name, pPerFrameConstantBuffer );
    CPUTAssetLibrary::GetAssetLibrary()->AddConstantBuffer( name, mpPerFrameConstantBuffer );
    SAFE_RELEASE(pPerFrameConstantBuffer); // We're done with it.  The CPUTBuffer now owns it.

    return result;
}
//-----------------------------------------------
HRESULT CPUTRenderTargetColor::CreateRenderTarget(
    std::string     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();

    // 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), "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), "Failed creating MSAA render target shader resource view" );
        CPUTSetDebugName( mpColorSRVMSAA, textureName + " ColorMSAA" );

        if( !recreate )
        {
            std::string msaaName = mName + "_MSAA";
            mpColorTextureMSAA = CPUTTextureDX11::Create( 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();
            std::string finalName;
            if( mName.at(0) == '$' )
            {
                finalName = msaaName;
            }else
            {
                CPUTFileSystem::ResolveAbsolutePathAndFilename( (pAssetLibrary->GetTextureDirectoryName() + 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), "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), "Failed creating render target shader resource view" );
    CPUTSetDebugName( mpColorSRV, textureName + " 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), "Failed creating render target buffer shader resource view" );
        CPUTSetDebugName( mpColorUAV, textureName + " Color Buffer" );
    }
    if( !recreate )
    {
        mpColorTexture = CPUTTextureDX11::Create(mName);
        pAssetLibrary->AddTexture( mName, "", "", mpColorTexture );

        mpColorBuffer = CPUTBuffer::Create(mName, NULL);
        ((CPUTBufferDX11*)mpColorBuffer)->SetUnorderedAccessView(mpColorUAV);
        //SeCPUTBufferDX11::CreateWithUAV(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), "Failed creating render target view" );
    CPUTSetDebugName( mpColorRenderTargetView, mName );

    return S_OK;
}
//-----------------------------------------------------------------------------
D3D11_MAPPED_SUBRESOURCE CPUTRenderTargetDepth::MapRenderTarget( CPUTRenderParameters &params, eCPUTMapType type, bool wait )
{
    // Mapping for DISCARD requires dynamic buffer.  Create dynamic copy?
    // Could easily provide input flag.  But, where would we specify? Don't like specifying in the .set file
    // Because mapping is something the application wants to do - it isn't inherent in the data.
    // Could do Clone() and pass dynamic flag to that.
    // But, then we have two.  Could always delete the other.
    // Could support programatic flag - apply to all loaded models in the .set
    // Could support programatic flag on model.  Load model first, then load set.
    // For now, simply support CopyResource mechanism.
    HRESULT hr;
    ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice();
    ID3D11DeviceContext *pContext = CPUT_DX11::GetContext();

    if( !mpDepthTextureDXStaging )
    {
        CD3D11_TEXTURE2D_DESC desc = mDepthDesc;
        // First time.  Create the staging resource
        desc.Usage = D3D11_USAGE_STAGING;
        switch( type )
        {
        case CPUT_MAP_READ:
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
            desc.BindFlags = 0;
            break;
        case CPUT_MAP_READ_WRITE:
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
            desc.BindFlags = 0;
            break;
        case CPUT_MAP_WRITE:
        case CPUT_MAP_WRITE_DISCARD:
        case CPUT_MAP_NO_OVERWRITE:
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            desc.BindFlags = 0;
            break;
        };
        HRESULT hr = pD3dDevice->CreateTexture2D( &desc, NULL, &mpDepthTextureDXStaging );
        ASSERT( SUCCEEDED(hr), "Failed to create staging texture" );
        CPUTSetDebugName( mpDepthTextureDXStaging, "Staging buffer" );
        UNREFERENCED_PARAMETER(hr);
    }
    else
    {
        ASSERT( mMappedType == type, "Mapping with a different CPU access than creation parameter." );
    }

    D3D11_MAPPED_SUBRESOURCE info;
    switch( type )
    {
    case CPUT_MAP_READ:
    case CPUT_MAP_READ_WRITE:
        // TODO: Copying and immediately mapping probably introduces a stall.
        // Expose the copy externally?
        // TODO: copy only if vb has changed?
        // Copy only first time?
        // Copy the GPU version before we read from it.
        // pContext->CopyResource( mpDepthTextureDXStaging, (mMultiSampleCount>1) ? mpDepthTextureDXMSAA : mpDepthTextureDX);
        // TODO: Do we (can we) support MSAA depth
        pContext->CopyResource( mpDepthTextureDXStaging, mpDepthTextureDX );
        break;
    };
    hr = pContext->Map( mpDepthTextureDXStaging, wait ? 0 : D3D11_MAP_FLAG_DO_NOT_WAIT, (D3D11_MAP)type, 0, &info );
    mMappedType = type;
    return info;
} // CPUTRenderTargetDepth::Map()
//-----------------------------------------------
HRESULT CPUTRenderTargetDepth::CreateRenderTarget(
    std::string     textureName,
    UINT        width,
    UINT        height,
    DXGI_FORMAT depthFormat,
    UINT        multiSampleCount,
    bool        recreate
)
{
    HRESULT result;

    mName             = textureName;
    mWidth            = width;
    mHeight           = height;
    mDepthFormat      = depthFormat;
    mMultiSampleCount = multiSampleCount;


    // NOTE: The following doesn't work for DX10.0 devices.
    // They don't support binding an MSAA depth texture as 

    // If we have a DX 10.1 or no MSAA, then create a shader resource view, and add a CPUTTexture to the AssetLibrary
    D3D_FEATURE_LEVEL featureLevel = gpSample->GetFeatureLevel();
    bool supportsResourceView = ( featureLevel >= D3D_FEATURE_LEVEL_10_1) || (mMultiSampleCount==1);

    D3D11_TEXTURE2D_DESC depthDesc = {
        width,
        height,
        1, // MIP Levels
        1, // Array Size
        DXGI_FORMAT(depthFormat - 1), //  DXGI_FORMAT_R32_TYPELESS
        mMultiSampleCount, 0,
        D3D11_USAGE_DEFAULT,
        D3D11_BIND_DEPTH_STENCIL | (supportsResourceView ? D3D11_BIND_SHADER_RESOURCE : 0),
        0, // CPU Access flags
        0 // Misc flags
    };

    // Create either a Texture2D, or Texture2DMS, depending on multisample count.
    D3D11_DSV_DIMENSION dsvDimension = (mMultiSampleCount>1) ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;

    ID3D11Device *pD3dDevice = CPUT_DX11::GetDevice();
    result = pD3dDevice->CreateTexture2D( &depthDesc, NULL, &mpDepthTextureDX );
    ASSERT( SUCCEEDED(result), "Failed creating depth texture.\nAre you using MSAA with a DX10.0 GPU?\nOnly DX10.1 and above can create a shader resource view for an MSAA depth texture." );

    D3D11_DEPTH_STENCIL_VIEW_DESC dsvd = { depthFormat, dsvDimension, 0 };
    result = pD3dDevice->CreateDepthStencilView( mpDepthTextureDX, &dsvd, &mpDepthStencilView );
    ASSERT( SUCCEEDED(result), "Failed creating depth stencil view" );
    CPUTSetDebugName( mpDepthStencilView, mName );

    if( supportsResourceView )
    {
        D3D11_SRV_DIMENSION srvDimension = (mMultiSampleCount>1) ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
        // Create the shader-resource view
        D3D11_SHADER_RESOURCE_VIEW_DESC depthRsDesc =
        {
            DXGI_FORMAT(depthFormat + 1),
            srvDimension,
            0
        };
        // TODO: Support optionally creating MIP chain.  Then, support MIP generation (e.g., GenerateMIPS()).
        depthRsDesc.Texture2D.MipLevels = 1;

        result = pD3dDevice->CreateShaderResourceView( mpDepthTextureDX, &depthRsDesc, &mpDepthResourceView );
        ASSERT( SUCCEEDED(result), "Failed creating render target shader resource view" );
        CPUTSetDebugName( mpDepthResourceView, textureName + " Depth" );

        if( !recreate )
        {
            CPUTAssetLibrary *pAssetLibrary = CPUTAssetLibrary::GetAssetLibrary();

            mpDepthTexture = CPUTTextureDX11::Create(mName);
            pAssetLibrary->AddTexture( mName, "", "", mpDepthTexture );
        }
        ((CPUTTextureDX11*)mpDepthTexture)->SetTextureAndShaderResourceView(mpDepthTextureDX, mpDepthResourceView);
    }
    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;
}
// find existing, or create new, ID3D11InputLayout layout
//-----------------------------------------------------------------------------
CPUTResult CPUTInputLayoutCacheDX11::GetLayout(
    ID3D11Device *pDevice,
    D3D11_INPUT_ELEMENT_DESC *pDXLayout,
    CPUTVertexShaderDX11 *pVertexShader,
    ID3D11InputLayout **ppInputLayout
){
    // Generate the vertex layout key
    LayoutKey layoutKey(pDXLayout, pVertexShader, true);

    // Do we already have one like this?
    if( mLayoutList[layoutKey] )
    {
        *ppInputLayout = mLayoutList[layoutKey];
        (*ppInputLayout)->AddRef();
        return CPUT_SUCCESS;
    }
    // Not found, create a new ID3D11InputLayout object

    // How many elements are in the input layout?
    int numInputLayoutElements=0;
    while(NULL != pDXLayout[numInputLayoutElements].SemanticName)
    {
        numInputLayoutElements++;
    }
    // Create the input layout
    HRESULT hr;
    ID3DBlob *pBlob = pVertexShader->GetBlob();
    hr = pDevice->CreateInputLayout( pDXLayout, numInputLayoutElements, pBlob->GetBufferPointer(), pBlob->GetBufferSize(), ppInputLayout );
    if (!SUCCEEDED(hr))
    {
        ID3D11ShaderReflection *pReflector = NULL;

        D3DReflect(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&pReflector);
        // Walk through the shader input bind descriptors.
        // If any of them begin with '@', then we need a unique material per model (i.e., we need to clone the material).
        int ii = 0;
        D3D11_SIGNATURE_PARAMETER_DESC desc;
        int i = 0;
        DEBUG_PRINT("Shader Inputs\n");
        while (SUCCEEDED(pReflector->GetInputParameterDesc(i, &desc)))
        {
            DEBUG_PRINT("\t%s\n", desc.SemanticName);
            i++;
        }
        DEBUG_PRINT("Mesh Inputs\n");
        for (int i = 0; i < numInputLayoutElements; i++)
        {
            DEBUG_PRINT("\t%s\n", pDXLayout[i].SemanticName);
        }
        DEBUG_PRINT("\n");
    }
    ASSERT( SUCCEEDED(hr), "Error creating input layout." );
    CPUTSetDebugName( *ppInputLayout, "CPUTInputLayoutCacheDX11::GetLayout()" );

    // Store this layout object in our map
    mLayoutList[layoutKey] = *ppInputLayout;

    // Addref for storing it in our map as well as returning it (count should be = 2 at this point)
    (*ppInputLayout)->AddRef();

    return CPUT_SUCCESS;
}