Example #1
0
/************************************************************************
*    desc:  Create the DirectX device for rendering
* 
*    return: bool - true on success or false on fail
************************************************************************/
void CXDevice::CreateXDevice( HWND hwnd )
{
    hWnd = hwnd;
    D3DDISPLAYMODE dxdm;
    HRESULT hresult;
    D3DFORMAT depthFormat[] = {D3DFMT_D32, D3DFMT_D24X8, D3DFMT_D16, (D3DFORMAT)0};
    D3DFORMAT selectedDepthFormat;
    int counter = 0;

    // Set the initial buffer clear mask
    if( CSettings::Instance().GetClearTargetBuffer() )
        bufferClearMask = D3DCLEAR_TARGET;

    // Recored the max and min z distances
    maximumZDist = CSettings::Instance().GetMaxZdist();
    minimumZDist = CSettings::Instance().GetMinZdist();
    viewAngle = D3DXToRadian( CSettings::Instance().GetViewAngle() );

    // Calc the aspect ratio
    float aspectRatio = CSettings::Instance().GetSize().w / 
                        CSettings::Instance().GetSize().h;

    // Calc the square percentage
    squarePercentage = CSettings::Instance().GetSize().h /
                       CSettings::Instance().GetSize().w;

    // calc the y ratio to the frustrum
    frustrumYRatio = squarePercentage / aspectRatio;

    // Create the DirectX 9 instance
    spDXInstance.Attach( Direct3DCreate9( D3D_SDK_VERSION ) );

    if( spDXInstance == NULL )
        throw NExcept::CCriticalException("DirectX Init Error",
            boost::str( boost::format("Error creating an instance of DirectX9.\n\n%s\nLine: %s") % __FUNCTION__ % __LINE__ ));

    // Get the caps to see if we can do hardware vertex processing
    if( FAILED( spDXInstance->GetDeviceCaps( D3DADAPTER_DEFAULT,
                                             D3DDEVTYPE_HAL,
                                             &d3dCaps ) ) )
        throw NExcept::CCriticalException("DirectX Init Error",
            boost::str( boost::format("Error getting device capabilities of video card.\n\n%s\nLine: %s") % __FUNCTION__ % __LINE__ ));

    // Get info about the video card
    if( FAILED( spDXInstance->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &dxdm ) ) )
        throw NExcept::CCriticalException("DirectX Init Error",
            boost::str( boost::format("Error getting adapter display mode of video card.\n\n%s\nLine: %s") % __FUNCTION__ % __LINE__ ));

    // Check for the best z buffer format
    do
    {
        selectedDepthFormat = depthFormat[counter];

        hresult = spDXInstance->CheckDeviceFormat( D3DADAPTER_DEFAULT,
                                                   D3DDEVTYPE_HAL,
                                                   dxdm.Format,
                                                   D3DUSAGE_DEPTHSTENCIL,
                                                   D3DRTYPE_SURFACE,
                                                   depthFormat[counter++] );
    }
    while( hresult != D3D_OK && depthFormat[counter] );

    // Tell them we couldn't secure a depth buffer
    if( hresult != D3D_OK )
        throw NExcept::CCriticalException("DirectX Init Error",
            boost::str( boost::format("Video card does not support depth buffering.\n\n%s\nLine: %s") % __FUNCTION__ % __LINE__ ));

    // clear out the structure
    memset( &dxpp, 0, sizeof(dxpp) );

    // Full screen or windowed mode
    dxpp.Windowed = !CSettings::Instance().GetFullScreen();

    // Fill out the remaining items of the structure
    dxpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
    dxpp.BackBufferFormat       = dxdm.Format;
    dxpp.BackBufferWidth        = (int)CSettings::Instance().GetSize().w;
    dxpp.BackBufferHeight       = (int)CSettings::Instance().GetSize().h;
    dxpp.hDeviceWindow          = hWnd;
    dxpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;
    dxpp.BackBufferCount        = 1;

    if( CSettings::Instance().GetTripleBuffering() )
        dxpp.BackBufferCount = 2;

    if( CSettings::Instance().GetVSync() )
        dxpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

    // Do we need the depth stencil? Z buffer and stencil are both created at the same time in hardware
    if( CSettings::Instance().GetCreateDepthStencilBuffer() )
    {
        dxpp.EnableAutoDepthStencil = true;
        dxpp.AutoDepthStencilFormat = selectedDepthFormat;
        depthStencilBufferClearMask = D3DCLEAR_ZBUFFER;

        if( CSettings::Instance().GetClearStencilBuffer() )
            depthStencilBufferClearMask |= D3DCLEAR_STENCIL;

        // check for stencil buffer support
        if( spDXInstance->CheckDepthStencilMatch( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, dxpp.BackBufferFormat, dxpp.BackBufferFormat, D3DFMT_D24FS8 ) != D3D_OK )
        {
            if( spDXInstance->CheckDepthStencilMatch( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, dxpp.BackBufferFormat, dxpp.BackBufferFormat, D3DFMT_D24S8 ) != D3D_OK )
            {
                if( spDXInstance->CheckDepthStencilMatch( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, dxpp.BackBufferFormat, dxpp.BackBufferFormat, D3DFMT_D24X4S4 ) != D3D_OK )
                {
                    if( spDXInstance->CheckDepthStencilMatch( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, dxpp.BackBufferFormat, dxpp.BackBufferFormat, D3DFMT_D24FS8 ) != D3D_OK )
                    {
                        throw NExcept::CCriticalException("DirectX Init Error",
                            boost::str( boost::format("Video card does not support hardware stencil buffer.\n\n%s\nLine: %s") % __FUNCTION__ % __LINE__ ));
                    }
                    else // support for a d15s1 buffer
                    {
                        dxpp.AutoDepthStencilFormat = D3DFMT_D15S1;
                    }
                }
                else // support for a d24x4s4 buffer
                {
                    dxpp.AutoDepthStencilFormat = D3DFMT_D24X4S4;
                }
            }
            else // support for a d24s8 buffer
            {
                dxpp.AutoDepthStencilFormat = D3DFMT_D24S8;
            }
        }
        else //support for a d24fs8 buffer
        {
            dxpp.AutoDepthStencilFormat = D3DFMT_D24FS8;
        }
    }

    DWORD dwBehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    if( d3dCaps.VertexProcessingCaps != 0 )    
        dwBehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;

    // Create the device
    if( FAILED( hresult = spDXInstance->CreateDevice( D3DADAPTER_DEFAULT,
                                         D3DDEVTYPE_HAL,
                                         hWnd,
                                         dwBehaviorFlags | D3DCREATE_MULTITHREADED,
                                         &dxpp, 
                                         &spDXDevice ) ) )
    {
        DisplayError( hresult );
    }

    // Calculate the projection matrixes
    CalcProjMatrix( CSettings::Instance().GetSize(),
                    CSettings::Instance().GetDefaultSize() );

    // Get the initial texture memory amount
    initialVideoMemory = GetAvailableTextureMem();
    
    // Buffers and render states that need to be reset/recreated after a device rest
    ResetXDevice();

}   // CreateXDevice
bool DX10_Renderer::onResize()
{
	// Release the old render target view before creating again
	ReleaseCOM(m_pRenderTargetView);
	ReleaseCOM(m_pDepthStencilView);
	ReleaseCOM(m_pDepthStencilBuffer);

	// Resize the buffers of the Swap Chain and create the new render target view
	VALIDATEHR(m_pDX10SwapChain->ResizeBuffers(1, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));

	// Create a temporary Back buffer
	ID3D10Texture2D* pBackBuffer;

	// Retrieve the Back Buffer of the Swap Chain and create a Render Target View using the Back Buffer
	VALIDATEHR(m_pDX10SwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&pBackBuffer)));
	VALIDATEHR(m_pDX10Device->CreateRenderTargetView(pBackBuffer, 0, &m_pRenderTargetView));

	// Release the memory from the temporary Back Buffer
	ReleaseCOM(pBackBuffer);

	// Create the depth buffer.
	D3D10_TEXTURE2D_DESC depthBufferDesc;

	depthBufferDesc.Width = m_clientWidth;
	depthBufferDesc.Height = m_clientHeight;
	depthBufferDesc.MipLevels = 1;
	depthBufferDesc.ArraySize = 1;
	depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthBufferDesc.SampleDesc.Count = 1; // multi sampling must match
	depthBufferDesc.SampleDesc.Quality = 0; // swap chain values.
	depthBufferDesc.Usage = D3D10_USAGE_DEFAULT;
	depthBufferDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL;
	depthBufferDesc.CPUAccessFlags = 0;
	depthBufferDesc.MiscFlags = 0;

	VALIDATEHR(m_pDX10Device->CreateTexture2D(&depthBufferDesc, NULL, &m_pDepthStencilBuffer));

	//--------------------------------------------------------------------------------------
	// Normal Depth Stencil
	//--------------------------------------------------------------------------------------
	D3D10_DEPTH_STENCIL_DESC depthStencilDesc;

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

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

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

	// Stencil operations if pixel is front-facing.
	depthStencilDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
	depthStencilDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
	depthStencilDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
	depthStencilDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;

	// Stencil operations if pixel is back-facing.
	depthStencilDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
	depthStencilDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
	depthStencilDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
	depthStencilDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;

	// Create the depth stencil state.
	VALIDATEHR(m_pDX10Device->CreateDepthStencilState(&depthStencilDesc, &m_pDepthStencilStateNormal));

	// Set the depth stencil state on the D3D device.
	m_pDX10Device->OMSetDepthStencilState(m_pDepthStencilStateNormal, 1);

	D3D10_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;

	// Initialize the depth stencil view.
	ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

	// Set up the depth stencil view description.
	depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthStencilViewDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
	depthStencilViewDesc.Texture2D.MipSlice = 0;

	// Create the depth stencil view.
	VALIDATEHR(m_pDX10Device->CreateDepthStencilView(m_pDepthStencilBuffer, &depthStencilViewDesc, &m_pDepthStencilView));

	// Bind the render target view and depth stencil buffer to the output render pipeline.
	m_pDX10Device->OMSetRenderTargets(1, &m_pRenderTargetView, m_pDepthStencilView);

	//--------------------------------------------------------------------------------------
	// Disabled Depth Stencil
	//--------------------------------------------------------------------------------------
	D3D10_DEPTH_STENCIL_DESC depthDisabledStencilDesc;

	// Clear the second depth stencil state before setting the parameters.
	ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc));

	// Now create a second depth stencil state which turns off the Z buffer for 2D rendering.
	depthDisabledStencilDesc.DepthEnable = false;
	depthDisabledStencilDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
	depthDisabledStencilDesc.DepthFunc = D3D10_COMPARISON_LESS;
	depthDisabledStencilDesc.StencilEnable = true;
	depthDisabledStencilDesc.StencilReadMask = 0xFF;
	depthDisabledStencilDesc.StencilWriteMask = 0xFF;
	depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
	depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
	depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
	depthDisabledStencilDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
	depthDisabledStencilDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
	depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
	depthDisabledStencilDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
	depthDisabledStencilDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;

	// Create the state using the device.
	VALIDATEHR(m_pDX10Device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_pDepthStencilStateZDisabled));

	// Set the View Port for the Device
	D3D10_VIEWPORT viewPort;
	viewPort.TopLeftX = 0;
	viewPort.TopLeftY = 0;
	viewPort.Width = m_clientWidth;
	viewPort.Height = m_clientHeight;
	viewPort.MinDepth = 0.0f;
	viewPort.MaxDepth = 1.0f;
	
	// Binds the View port to the Rasterizer stage of the pipeline
	m_pDX10Device->RSSetViewports(1, &viewPort);

	// Calculate the new Projection Matrix
	CalcProjMatrix();

	// Create an orthographic projection matrix for 2D rendering.
	D3DXMatrixOrthoLH(&m_matOrtho, static_cast<float>(m_clientWidth), static_cast<float>(m_clientHeight), 0.1f, 100.0f);

	return true;
}