The reference of the IDXGIFactory interface tells me, that in order to create a swap chain, I might use the same factory that was used to create the Direct3D device:
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.
It also gives the following code exmaple:
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);
The article is very spare and when trying to fully understand it, the following two questions arose, whereas the first question is the main question (concerning the title of this thread):
Why do I have to use the same factory that was used to create the Direct3D device in order to create the swap chain? Does the factory instance maintain an internal state which is important or is it just to avoid to create another instance of the factory which consumes resources?
Also, within the code sample I struggle with the following line of code:
hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);
To me, it is not logical, that the IDXGIAdapter is the the parent of the IDXGIDevice. Otherwise I would expect the IDXGIAdapter to have a method like CreateDevice which would make the adapter the parent of the device. But that is not the case. Why is the adapter the parent of the device?
The root of the problem goes back to DXGI 1.0 (Direct3D 10) and DXGI 1.1 (Direct3D 11). If you tried to use a IDXGIFactory
created by both CreateDXGIFactory
and CreateDXGIFactory1
in the same process, things would go pear-shaped pretty quick.
The other issue is that there's an implicit factory created when you use the 'default device' with Direct3D 10.x or 11.x device creation. The 'magic code sequence' above lets you get the factory created implicitly.
The second step in the docs should be dxgiDevice->GetAdapter
not dxgiDevice->GetParent
. I'll file a doc bug on that.
This is even easier to do if using 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
Note that this whole area has been cleaned up with Direct3D 12, and you can't use QI to get an IDXGIDevice
from a ID3D12Device
.
References
DirectX Graphics Infrastructure (DXGI): Best Practices
Anatomy of Direct3D 11 Create Device