D3D11 SwapChain confusion

Started by
4 comments, last by Erik Rufelt 14 years, 1 month ago
I am trying to use D3D11CreateDevice and IDXGIFactory::CreateSwapChain instead of the usual D3D11CreateDeviceAndSwapChain for a few reasons. The first is I want to keep my rendering abstraction unaware of whether a render target is just a texture, or in fact a window. The second reason is that I want to be able to render to multiple windows, each of which require a swap chain. The problem is, from my RenderWindow class if I create am IDXGIFactory and try to create a swapchain with it, even when I query the IDXGIDevice from the ID3D11Device, I get the following warning in the output window: DXGI Warning: IDXGIFactory::CreateSwapChain: This function is being called with a device from a different IDXGIFactory. What I have done as an alternative is something like this:
IDXGIDevice* pDXGIDevice = NULL;
if(SUCCEEDED(hr)) hr = pD3D11Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDXGIDevice));

IDXGIAdapter* pDXGIAdapter = NULL;
if(SUCCEEDED(hr)) hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDXGIAdapter));

IDXGIFactory* pDXGIFactory = NULL;
if(SUCCEEDED(hr)) hr = pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDXGIFactory));
Which seems to work, but I seem to be jumping through a lot of hoops to get to where I want. Is there an alternative or should I just hide that code away in a function somewhere and move on?
Advertisement
In D3D11, when you create the device with a null adapter pointer, a new DXGI factory is created internally (using DXGI 1.1) which is why you need to jump through those QI hoops.

You also might try using CreateDXGIFactory1 instead of CreateDXGIFactory.
Your observation is correct. More information can be found here.
Thanks for the info! I'm not new to C++ or dealing with COM interfaces but new to DXGI and DX11 so sometimes I have to stop and wonder if I'm taking the long way round!
I had a very similar issue as well...this is how I ended up implementing it.

Don't know if there's a better way, but it works fine for me (need multiple windows and swap chains)...

u32 device_flags = D3D10_CREATE_DEVICE_SINGLETHREADED;

#ifdef _DEBUG
device_flags |= D3D10_CREATE_DEVICE_DEBUG;
#endif // _DEBUG

HRESULT hr = D3D10CreateDevice( NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, device_flags, D3D10_SDK_VERSION, & m_pDevice );

if ( hr != S_OK )
{
TRACE("cDX10Mananger::Initialise(): Unable to create DX10 device (hr = 0x%0X)\n", hr );
return false;
}
else
{
TRACE("cDX10Mananger::Initialise(): Create DX10 device OK !\n");
}

hr = m_pDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)& m_pDXGIDevice);

if ( hr != S_OK )
{
TRACE("cDX10Mananger::Initialise(): Unable to get DXGIDevice (hr = 0x%0X)\n", hr );
return false;
}

hr = m_pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)& m_pDXGIAdapter);

if ( hr != S_OK )
{
TRACE("cDX10Mananger::Initialise(): Unable to get DXGIAdapter (hr = 0x%0X)\n", hr );
return false;
}

hr = m_pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)& m_pDXGIFactory);

if ( hr != S_OK )
{
TRACE("cDX10Mananger::Initialise(): Unable to get DXGIFactory (hr = 0x%0X)\n", hr );
return false;
}
You could also create the DXGI factory before the device and pass the adapter manually, as enumerated from the factory. According to the documentation passing NULL for the adapter automatically uses the adapter first enumerated by IDXGIFactory::EnumAdapters. This is also a good idea if you want to be able to run on different adapters on multi-monitor systems.

This topic is closed to new replies.

Advertisement