了解 DirectX11 和 Directx11.1 示例 msdn 代码

Understanding DirectX11 and Directx11.1 sample msdn code

在为 win32 初始化 DirectX 11.1 时,我遵循了 MSDN 示例代码。 代码声明了两个 Direct3d 设备:

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

然后像这样获取设备:

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;

然后我们获取DXGIDevice:

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

然后我们得到适配器:

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

从适配器我们得到 IDXGIFactory1 接口:

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

从IDXGIFactory1接口,我们请求IDXGIFactory2接口:

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

如果IDXGIFactory2可用,我们请求Direct3D11.1设备接口。 同时获取ID3D11DeviceContext1接口:

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) 
                        );
    }

然后我们创建交换链:

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

我的第一个问题是为什么这段代码在创建交换链时使用 DirectX11 版本的设备?我们应该使用 g_pd3dDevice1 而不是 g_pd3dDevice 吗?

我的第二个问题是,虽然我们可以获取directx11.1版本的接口,但是msdn示例代码是从IDXGISwapChain1接口获取IDXGISwapChain接口:

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

并在当前调用中使用该版本的交换链:

g_pSwapChain->Present( 0, 0 );

这是为什么?

您指的是 Direct3D Win32 教程 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.

首先要说的是,这里的大部分复杂性是确保教程代码在 DirectX 11.0 系统(WindowsVista SP2+KB971644, Windows 7 RTM, Windows 7 SP1 without KB2670838) as well as DirectX 11.1 or later (Windows 7 SP1+KB2670838、Windows8、或以后)。 Windows 8 Store 或通用 Windows 应用程序不需要 运行 在 DirectX 11.0 系统上可以从不依赖 运行。

g_pd3dDeviceg_pd3dDevice1 对象实例实际上是同一个对象,只是具有不同的接口。将 QueryInterface 视为类似于 C++ 的 dynamic_castg_pSwapChaing_pSwapChain1也是如此。

用于获取 Direct3D 11.1 设备和设备上下文(如果可用)的代码实际上可以位于 InitDevice 函数中的任何位置。在 Direct3D VS Win32 Game Template 中,我在创建设备之后有这个,但在我创建交换链之前,所以它们不需要捆绑在一起。我将这段代码放在教程中的交换链 if 语句中,以适应两种注释情况:"DirectX 11.1 or later" 和 "DirectX 11.0",它们对于 DXGI 1.1 和 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.

我将 g_pSwapChain 用于 Present,这样我就不需要为 DirectX 11.0 和 DirectX 11.1 使用两个不同的代码路径。除非您使用较新的 DXGI 1.2 方法,否则您可以使用此处的基本方法。

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

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