Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding DirectX11 and Directx11.1 sample msdn code

Tags:

c++

directx-11

When initializing DirectX 11.1 for win32 I was following MSDN sample code. The code declare two Direct3d devices:

   ID3D11Device*           g_pd3dDevice = nullptr;
   ID3D11Device1*          g_pd3dDevice1 = nullptr;

and then acquire the device like:

D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
     };

UINT numFeatureLevels = ARRAYSIZE( featureLevels );


hr = D3D11CreateDevice( 
                        nullptr, 
                        D3D_DRIVER_TYPE_HARDWARE, 
                        nullptr, 
                        createDeviceFlags, 
                        featureLevels, 
                        numFeatureLevels,
                        D3D11_SDK_VERSION, 
                        &g_pd3dDevice, 
                        &g_featureLevel, 
                       &g_pImmediateContext );

if ( hr == E_INVALIDARG )
{

    hr = D3D11CreateDevice( 
                            nullptr, 
                            D3D_DRIVER_TYPE_HARDWARE, 
                            nullptr, 
                            createDeviceFlags, 
                            &featureLevels[1], 
                            numFeatureLevels - 1,
                            D3D11_SDK_VERSION, 
                            &g_pd3dDevice, 
                            &g_featureLevel, 
                            &g_pImmediateContext );
}

if( FAILED( hr ) )
    return hr;

Then we acquire DXGIDevice:

IDXGIFactory1* dxgiFactory = nullptr;
IDXGIDevice* dxgiDevice = nullptr;
hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice),
                                   reinterpret_cast<void**>(&dxgiDevice) 
                                  );

Then we get the adapter:

IDXGIAdapter* adapter = nullptr;
hr = dxgiDevice->GetAdapter(&adapter);

From the adapter we get the IDXGIFactory1 interface:

 hr = adapter->GetParent( __uuidof(IDXGIFactory1), 
                          reinterpret_cast<void**>(&dxgiFactory) );

From the IDXGIFactory1 interface, we request IDXGIFactory2 interface:

IDXGIFactory2* dxgiFactory2 = nullptr;
hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2),
                                   reinterpret_cast<void**>(&dxgiFactory2)
                                 );

If IDXGIFactory2 is available, we request Direct3D11.1 device interface. Also get the ID3D11DeviceContext1 interface:

if ( dxgiFactory2 )
{
 // DirectX 11.1 or later
 hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1),
                                   reinterpret_cast<void**>(&g_pd3dDevice1)
                                   );
    if (SUCCEEDED(hr))
    {
        (void) g_pImmediateContext->QueryInterface(   
                          __uuidof(ID3D11DeviceContext1), 
                          reinterpret_cast<void**> (&g_pImmediateContext1) 
                        );
    }

Then we create the swapchain:

hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, 
                                           g_hWnd, 
                                           &sd, 
                                           nullptr, 
                                           nullptr, 
                                           &g_pSwapChain1 );

My first question is why this code is using DirectX11 version of device while creating the swapchain? Should we use the g_pd3dDevice1 instead of g_pd3dDevice?

My second question is, even though we could acquire directx11.1 version of interfaces, the msdn sample code acquired the IDXGISwapChain interface from IDXGISwapChain1 interface:

hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain),
                             reinterpret_cast<void**>(&g_pSwapChain) );

and use that version of swapchain in the present call:

g_pSwapChain->Present( 0, 0 );

Why is that?

like image 324
Pixelord Avatar asked Oct 31 '22 21:10

Pixelord


1 Answers

You are referring to the Direct3D Win32 Tutorial that is on MSDN Code Gallery. Note that there's also a version on GitHub.

Disclaimer: This is all stuff I've mined from the legacy DirectX SDK so they are all unofficial samples. The official Windows SDK samples are for Windows 8 Store or universal Windows apps on Windows 10. While these samples are unofficial, as I'm the last developer to work on the legacy DirectX SDK, they are at least authoritative.

The first thing to say is that most of the complexity here is ensuring that the tutorial code works correctly on DirectX 11.0 systems (Windows Vista SP2+KB971644, Windows 7 RTM, Windows 7 SP1 without KB2670838) as well as DirectX 11.1 or later (Windows 7 SP1+KB2670838, Windows 8, or later). This is not needed for Windows 8 Store or universal Windows apps which can rely on never running on DirectX 11.0 systems.

Both the g_pd3dDevice and g_pd3dDevice1 object instances are really the same object, just with different interfaces. Think of QueryInterface as being something like C++'s dynamic_cast. The same is true of g_pSwapChain and g_pSwapChain1.

The code for grabbing the Direct3D 11.1 device and device context if available could really be anywhere in the InitDevice function. In the Direct3D VS Win32 Game Template I have this after the create device, but before I create the swap chain so they don't need to be tied together. I put this code in the swapchain if statement in the tutorial to fit with the two commented cases: "DirectX 11.1 or later" and "DirectX 11.0" which are different for DXGI 1.1 vs. DXGI 1.2+.

 // DirectX 11.1 or later
 hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1),
                                   reinterpret_cast<void**>(&g_pd3dDevice1)
                                   );
 if (SUCCEEDED(hr))
 {
        (void) g_pImmediateContext->QueryInterface(   
                          __uuidof(ID3D11DeviceContext1), 
                          reinterpret_cast<void**> (&g_pImmediateContext1) 
                        );
 }

The code in the Win32 tutorial you are looking at is also a lot simpler in the VS Win32 Game template because I make use of Microsoft::WRL::ComPtr.

I use g_pSwapChain for the Present so that I don't need to have two different code paths for DirectX 11.0 vs. DirectX 11.1. Unless you are using the newer DXGI 1.2 methods, you can use the base one here just fine.

DXGI 1.0 was released for DirectX 10.0. DXGI 1.1 is for DirectX 11.0. DXGI 1.2 is DirectX 11.1.

See Anatomy of Direct3D 11 Create Device, Direct3D Win32 Game Visual Studio template and DirectX Tool Kit Tutorials.

like image 168
Chuck Walbourn Avatar answered Nov 15 '22 05:11

Chuck Walbourn