在为 win32 初始化 DirectX 11.1 时,我遵循了 MSDN 示例代码。代码声明了两个 Direct3d 设备:
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11Device1* g_pd3dDevice1 = nullptr;
Run Code Online (Sandbox Code Playgroud)
然后获取设备,如:
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;
Run Code Online (Sandbox Code Playgroud)
然后我们获取DXGIDevice:
IDXGIFactory1* dxgiFactory = nullptr;
IDXGIDevice* dxgiDevice = nullptr;
hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice),
reinterpret_cast<void**>(&dxgiDevice)
);
Run Code Online (Sandbox Code Playgroud)
然后我们得到适配器:
IDXGIAdapter* adapter = nullptr;
hr = dxgiDevice->GetAdapter(&adapter);
Run Code Online (Sandbox Code Playgroud)
从适配器我们得到 IDXGIFactory1 接口:
hr = adapter->GetParent( __uuidof(IDXGIFactory1),
reinterpret_cast<void**>(&dxgiFactory) );
Run Code Online (Sandbox Code Playgroud)
从 IDXGIFactory1 接口,我们请求 IDXGIFactory2 接口:
IDXGIFactory2* dxgiFactory2 = nullptr;
hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2),
reinterpret_cast<void**>(&dxgiFactory2)
);
Run Code Online (Sandbox Code Playgroud)
如果 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)
);
}
Run Code Online (Sandbox Code Playgroud)
然后我们创建交换链:
hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice,
g_hWnd,
&sd,
nullptr,
nullptr,
&g_pSwapChain1 );
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是为什么此代码在创建交换链时使用 DirectX11 版本的设备?我们应该使用 g_pd3dDevice1 而不是 g_pd3dDevice 吗?
我的第二个问题是,尽管我们可以获取directx11.1版本的接口,但msdn示例代码从IDXGISwapChain1接口获取了IDXGISwapChain接口:
hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain),
reinterpret_cast<void**>(&g_pSwapChain) );
Run Code Online (Sandbox Code Playgroud)
并在当前调用中使用该版本的交换链:
g_pSwapChain->Present( 0, 0 );
Run Code Online (Sandbox Code Playgroud)
这是为什么?
您指的是MSDN Code Gallery上的Direct3D Win32 教程。请注意, GitHub上也有一个版本。
免责声明:这些都是我从旧版 DirectX SDK中挖掘的内容,因此它们都是非官方示例。官方 Windows SDK 示例适用于Windows 8 应用商店或Windows 10 上的通用 Windows 应用程序。虽然这些示例是非官方的,但由于我是最后一个使用旧版 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_pd3dDevice和g_pd3dDevice1对象实例实际上是同一个对象,只是具有不同的接口。可以将其视为QueryInterface类似于 C++ 的dynamic_cast. g_pSwapChain和也是如此g_pSwapChain1。
用于获取 Direct3D 11.1 设备和设备上下文(如果可用)的代码实际上可以位于函数中的任何位置InitDevice。在Direct3D VS Win32 游戏模板中,我在创建设备之后、创建交换链之前有此模板,因此它们不需要捆绑在一起。我将此代码放在教程中的交换链 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)
);
}
Run Code Online (Sandbox Code Playgroud)
您正在查看的 Win32 教程中的代码在 VS Win32 游戏模板中也简单得多,因为我使用了
Microsoft::WRL::ComPtr.
我使用g_pSwapChainfor ,Present这样我就不需要为 DirectX 11.0 和 DirectX 11.1 设置两个不同的代码路径。除非您使用较新的 DXGI 1.2 方法,否则您可以在此处使用基本方法。
DXGI 1.0 针对 DirectX 10.0 发布。DXGI 1.1 适用于 DirectX 11.0。DXGI 1.2 是 DirectX 11.1。
请参阅Direct3D 11 创建设备剖析、Direct3D Win32 游戏 Visual Studio 模板和DirectX 工具包教程。