Understanding the purpose of a code snippet from Diredt3D tutorial, and some terminology

Started by
2 comments, last by Infinisearch 9 years, 6 months ago

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.

Advertisement
DXGI is the DirectX Graphics Interface. Its just a COM object that's used to query which GPUs your system has (some people have more than one) and to create SwpChain objects.

A SwapChain is what binds a D3D render target to a window. It also provides some related services like handling full screen transitions, double and triple buffer mode, etc.

The CreateDevice and CreateDeviceAndSwapChain functions are helpers that create said objects using the default DXGIFactory. Unfirtubstrly they don't return the factory so if you need it for anything else you have to do the COM query dance you see in this code.

Some people create the device without a swap chain shey write code like this to grab the factory from the device and then create the swap chain. Using CreateDrviceAndSeapChain you wouldn't have to do this.

Sean Middleditch – Game Systems Engineer – Join my team!

Hello sir, thank you for your reply

May I ask you to check my understanding to make sure have some kind of ideas whats going on:

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?

DXGI is the DirectX Graphics Interface. Its just a COM object that's used to query which GPUs your system has (some people have more than one) and to create SwpChain objects.

So to describe simply what is going on, "enumerating graphics adapters" means going through the system and seeing what gpus are available to use (such as an integrated one into a cpu, or a dedicated hardware card). "enumerating display modes" on the other hands looks what physical monitor is connected to these gpu's and what its resolution and properties are (such as the specs of a Dell monitor running?)

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?

Question 4. Why are we doing this? What is this actually doing or looking at physically (as in terms of computer hardware...?)

We are adding this object, because its job is to search for the GPU's and provide us access to work with them

A SwapChain is what binds a D3D render target to a window. It also provides some related services like handling full screen transitions, double and triple buffer mode, etc.

These terms still confuse me no matter how much I read their descriptions. So the SwapChain could be visualized as follows:

CP5nwJf.jpg

In this case I am trying to show a very simple idea of a swapChain consisting of a 30x30 final render area (on our monitor). Each square represents a possible pixel that we will see? SO it is literally two areas of memory where each block holds the final color (after some fancy DX maths)?

The render target still confuses me... the MSDN says "A render target is a memory buffer for rendering pixels.".. How is that different from the swap chain? is it just some other random area that is not the swapChain? (Like the equivalent of system RAM??) Is it held on the GPU or inside the RAM?

The CreateDevice and CreateDeviceAndSwapChain functions are helpers that create said objects using the default DXGIFactory. Unfirtubstrly they don't return the factory so if you need it for anything else you have to do the COM query dance you see in this code.

So once we have our device (the IDE's representation of our video card?) and the swap chain (somewhere on the video card...?). I dont fully understand what you mean by "they dont return the factory"? Is this "factory dance" used to just fully find out all possible gpus that we can use for DirectX on the current system?

Some people create the device without a swap chain shey write code like this to grab the factory from the device and then create the swap chain. Using CreateDrviceAndSeapChain you wouldn't have to do this.

Again I am not 100% sure what you mean by "grab the factory from the device"...

Is there a way to visualize these kinds of thing such as what exactly each function is looking at or doing in terms of the non video side of things:

(motherboard, cpu, ram),

and video side

(video card, video cards cores, video cards ram).

Eg. the swap chain is created on the video cards ram? But we need to know where the hardware address is in order to program it to the IDE...? Am I on the right track?

Thanks again for all your time.


The render target still confuses me... the MSDN says "A render target is a memory buffer for rendering pixels.".. How is that different from the swap chain? is it just some other random area that is not the swapChain? (Like the equivalent of system RAM??) Is it held on the GPU or inside the RAM?

You don't have to render to the back buffer you can render to a texture(or multiple textures or multiple at the same time) as well if you setup your textures to be capable of being render targets. However if you want to display something on the screen, eventually you wind up rendering to the back buffer. Lookup environment maps, and deferred rendering for examples of why you'd use them.

-potential energy is easily made kinetic-

This topic is closed to new replies.

Advertisement