Sign in to follow this  
Neilo

D3D11 SwapChain confusion

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this