为什么对设备和交换链使用相同的 IDXGIFactory
Why use the same IDXGIFactory for Device and Swap Chain
IDXGIFactory interface 的参考告诉我,为了创建交换链,我可能会使用用于创建 Direct3D 设备的同一工厂:
Because you can create a Direct3D device without creating a swap chain, you might need to retrieve the factory that is used to create the device in order to create a swap chain.
它还给出了以下代码示例:
IDXGIDevice * pDXGIDevice;
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter * pDXGIAdapter;
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
IDXGIFactory * pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
这篇文章非常简洁,在试图完全理解它时,出现了以下两个问题,而第一个问题是主要问题(关于本帖的标题):
为什么我必须使用用于创建 Direct3D 设备的同一个工厂才能创建交换链?工厂实例是否维护重要的内部状态,还是只是为了避免创建另一个消耗资源的工厂实例?
此外,在代码示例中,我遇到了以下代码行:
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
对我来说,IDXGIAdapter 是 IDXGIDevice 的 parent 是不合逻辑的。否则我希望 IDXGIAdapter 有一个像 CreateDevice 这样的方法,它会使适配器成为设备的 parent。但事实并非如此。为什么适配器是设备的parent?
问题的根源可以追溯到 DXGI 1.0 (Direct3D 10) 和 DXGI 1.1 (Direct3D 11)。如果您尝试在同一进程中使用由 CreateDXGIFactory
和 CreateDXGIFactory1
创建的 IDXGIFactory
,事情会很快变得糟糕。
另一个问题是,当您将 'default device' 与 Direct3D 10.x 或 11.x 设备创建一起使用时,会创建一个隐式工厂。上面的 'magic code sequence' 让您可以隐式创建工厂。
文档中的第二步应该是 dxgiDevice->GetAdapter
而不是 dxgiDevice->GetParent
。我会就此提交文档错误。
如果使用 Microsoft::WRL::ComPtr
:
,这会更容易做到
// First, retrieve the underlying DXGI Device from the D3D Device
ComPtr<IDXGIDevice1> dxgiDevice;
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
// Identify the physical adapter (GPU or card) this device is running on.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
// And obtain the factory object that created it.
ComPtr<IDXGIFactory1> dxgiFactory;
DX::ThrowIfFailed(dxgiAdapter->GetParent(__uuidof(IDXGIFactory1), &dxgiFactory));
Direct3D 12
请注意,这整个区域已被 Direct3D 12 清理干净,您无法使用 QI 从 ID3D12Device
中获取 IDXGIDevice
。
参考资料
DirectX Graphics Infrastructure (DXGI): Best Practices
Anatomy of Direct3D 11 Create Device
IDXGIFactory interface 的参考告诉我,为了创建交换链,我可能会使用用于创建 Direct3D 设备的同一工厂:
Because you can create a Direct3D device without creating a swap chain, you might need to retrieve the factory that is used to create the device in order to create a swap chain.
它还给出了以下代码示例:
IDXGIDevice * pDXGIDevice;
hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
IDXGIAdapter * pDXGIAdapter;
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
IDXGIFactory * pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);
这篇文章非常简洁,在试图完全理解它时,出现了以下两个问题,而第一个问题是主要问题(关于本帖的标题):
为什么我必须使用用于创建 Direct3D 设备的同一个工厂才能创建交换链?工厂实例是否维护重要的内部状态,还是只是为了避免创建另一个消耗资源的工厂实例?
此外,在代码示例中,我遇到了以下代码行:
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
对我来说,IDXGIAdapter 是 IDXGIDevice 的 parent 是不合逻辑的。否则我希望 IDXGIAdapter 有一个像 CreateDevice 这样的方法,它会使适配器成为设备的 parent。但事实并非如此。为什么适配器是设备的parent?
问题的根源可以追溯到 DXGI 1.0 (Direct3D 10) 和 DXGI 1.1 (Direct3D 11)。如果您尝试在同一进程中使用由 CreateDXGIFactory
和 CreateDXGIFactory1
创建的 IDXGIFactory
,事情会很快变得糟糕。
另一个问题是,当您将 'default device' 与 Direct3D 10.x 或 11.x 设备创建一起使用时,会创建一个隐式工厂。上面的 'magic code sequence' 让您可以隐式创建工厂。
文档中的第二步应该是 dxgiDevice->GetAdapter
而不是 dxgiDevice->GetParent
。我会就此提交文档错误。
如果使用 Microsoft::WRL::ComPtr
:
// First, retrieve the underlying DXGI Device from the D3D Device
ComPtr<IDXGIDevice1> dxgiDevice;
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
// Identify the physical adapter (GPU or card) this device is running on.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
// And obtain the factory object that created it.
ComPtr<IDXGIFactory1> dxgiFactory;
DX::ThrowIfFailed(dxgiAdapter->GetParent(__uuidof(IDXGIFactory1), &dxgiFactory));
Direct3D 12
请注意,这整个区域已被 Direct3D 12 清理干净,您无法使用 QI 从 ID3D12Device
中获取 IDXGIDevice
。
参考资料
DirectX Graphics Infrastructure (DXGI): Best Practices
Anatomy of Direct3D 11 Create Device