【问题标题】:Understanding DirectX11 and Directx11.1 sample msdn code了解 DirectX11 和 Directx11.1 示例 msdn 代码
【发布时间】:2015-08-17 08:15:00
【问题描述】:

在为 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 );

这是为什么呢?

【问题讨论】:

  • 当然,这是一个典型的复制/粘贴错误。无论如何它肯定工作得很好,因为接口的实际实现是11.1代码。第二个只是更容易保持渲染循环与旧 DX 版本兼容。
  • 感谢您的评论。你能解释一下,g_pd3dDevice的实际接口是11.1吗?因为当我在 g_pd3dDevice 上使用 CreateRasterizerState1 时,我没有编译。但它适用于 g_pd3dDevice1。
  • 实现是11.1,不是接口。你看不到它。这是 Microsoft 用来保持其代码向后兼容的标准技术。
  • 好的明白了。谢谢。

标签: c++ directx-11


【解决方案1】:

您指的是MSDN Code Gallery 上的Direct3D Win32 教程。请注意,GitHub 上还有一个版本。

免责声明:这是我从legacy DirectX SDK 挖掘的所有内容,因此它们都是非官方样本。官方 Windows SDK 示例适用于 Windows 8 Storeuniversal Windows apps on Windows 10。虽然这些示例是非官方的,但由于我是最后一个使用旧版 DirectX SDK 的开发人员,它们至少是权威的。

首先要说的是,这里的大部分复杂性是确保教程代码在 DirectX 11.0 系统(Windows Vista SP2+KB971644、Windows 7 RTM、没有 KB2670838 的 Windows 7 SP1)以及 DirectX 11.1 上正常工作或更高版本(Windows 7 SP1+KB2670838、Windows 8 或更高版本)。 Windows 8 应用商店或通用 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 或更高版本”和“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) 
                        );
 }

您正在查看的 Win32 教程中的代码在 VS Win32 游戏模板中也简单得多,因为我使用了Microsoft::WRL::ComPtr

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

为 DirectX 10.0 发布了 DXGI 1.0。 DXGI 1.1 适用于 DirectX 11.0。 DXGI 1.2 是 DirectX 11.1。

请参阅Anatomy of Direct3D 11 Create DeviceDirect3D Win32 Game Visual Studio templateDirectX Tool Kit Tutorials

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多