I am learning how to implement graphics using DirectX 11 using the following tutorial series:
https://code.msdn.microsoft.com/Direct3D-Tutorial-Win32-829979ef
I cannot for the life of me understand what this portion of code is doing (Tutorial01.cpp):
// Obtain DXGI factory from device (since we used nullptr for pAdapter above)
IDXGIFactory1* dxgiFactory = nullptr;
{
IDXGIDevice* dxgiDevice = nullptr;
hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) );
if (SUCCEEDED(hr))
{
IDXGIAdapter* adapter = nullptr;
hr = dxgiDevice->GetAdapter(&adapter);
if (SUCCEEDED(hr))
{
hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) );
adapter->Release();
}
dxgiDevice->Release();
}
}
if (FAILED(hr))
return hr;
// Create swap chain
IDXGIFactory2* dxgiFactory2 = nullptr;
hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) );
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) );
}
DXGI_SWAP_CHAIN_DESC1 sd;
ZeroMemory(&sd, sizeof(sd));
sd.Width = width;
sd.Height = height;
sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 );
if (SUCCEEDED(hr))
{
hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) );
}
dxgiFactory2->Release();
}
else
{
// DirectX 11.0 systems
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain );
}
dxgiFactory->Release();
I would be grateful if you could bear with me through my thought process, and clear up some of my confusions.
They start by defining
IDXGIFactory1* dxgiFactory = nullptr;
so I jump on the msdn to read about IDXGIFactory1...
"The IDXGIFactory1 interface implements methods for generating DXGI objects."
okay, so what exactly is this DXGI they talk about?
"Microsoft DirectX Graphics Infrastructure (DXGI) handles enumerating graphics adapters, enumerating display modes,..."
Question 1. What is the physical meaning of "enumerating graphics adapters", and "enumerating display modes"?
Question 2. With this in mind, what exactly are DXGI objects?
Then they create a...
IDXGIDevice* dxgiDevice = nullptr;
where a IDXGIDevice is defined as:
"An IDXGIDevice interface implements a derived class for DXGI objects that produce image data."
Question 3. Can someone please explain why this dxgiDevice is added now? What is its purpose? Why is it useful? Why do we WANT it?
continuing... the next line of code:
hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) );
I read what all of the functions do on the msdn, but it just isn't coming together... the msdn states that what we get from this line of code is:
The address of a pointer variable that receives the interface pointer requested in the riid parameter. Upon successful return, *ppvObject contains the requested interface pointer to the object.
Question 4. Why are we doing this? What is this actually doing or looking at physically (as in terms of computer hardware...?)
continuing... if this function successfully gets this interface pointer...
IDXGIAdapter* adapter = nullptr;
arrrghh... another one. To the msdn!
The IDXGIAdapter interface represents a display sub-system (including one or more GPU's, DACs and video memory).
okay, that seems a bit more self explanatory. I can now understand this as an actual physical object residing somewhere on or in the computer.
hr = dxgiDevice->GetAdapter(&adapter);
This gives us "The address of an IDXGIAdapter interface pointer to the adapter."
Question 5. Again what does this actually mean? Is it something like the location on the motherboard that the compiler can use to talk to the graphics adapter? The "hardware address" of the GPU?
continuing...
if (SUCCEEDED(hr))
{
hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) );
adapter->Release();
}
dxgiDevice->Release();
Question 6. This GetParent seems to be the ultimate goal of this entire operation. What is its purpose? Why do we want it? What have we ultimately done with all of this code? And why, after its all done, do we just call Release()?
Then, I wont do the same breakdown, but the similar set of code happens this time with a
IDXGIFactory2* dxgiFactory2 = nullptr;
and starting to fill out the DXGI_SWAP_CHAIN_DESC1, or a DXGI_SWAP_CHAIN_DESC if they don't retrieve a dxgiFactory2??
Question 7. With my previous questions in mind, can you please wrap up in a nutshell what the full code is doing? Please whenever possible don't use terms like device or interface, because they are plastered all over the msdn, and while I am happy to read it and memorize it, I really have no idea what any of it means to the actual computer...
Thank you tremendously for your time.