# unable to create a IDXGIDevice with D3D12CreateDevice()

I was trying to do a bare bones simple build similar to some Directx samples. First I have to use __uuid() instead of IID_PPV_ARGS() in D3D12CreateDevice() in order to get an HRESULT=S_OK. But then when I try to create a command queue with CreateCommandQueue visual studio says that the device object which is really a com pointer ComPtr<IDXGIDevice> doesn't have a member function CreateCommandQueue, even though when I look through the D3D12.h header I can see it declare it as a public member.

• Let's get the obvious out of the way: are you sure your GPU supports D3D12? – Bálint Nov 12 '16 at 10:13
• @I was almost entirely certain, but I figured it out. I was making simple mistake of passing a ComPtr<IDXGIDevice> instance pointer instead of a ComPtr<ID3D12Device>. So basically the device is supposed to come from D3D12 not DXGI. Some how I forced it to compile and was way off in that mess. – marshal craft Nov 12 '16 at 11:18
• Then post that as an answer – Bálint Nov 12 '16 at 11:24

A bare-minimum would be:

ComPtr<ID3D12Device> device;
HRESULT hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device));
if (FAILED(hr))
// Error!


This will fail if the default device doesn't have an updated WDDM 2.0 driver that supports DirectX 12.

This program would also fail to run/bind on a system older than Windows 10 because D3D12CreateDevice in d3d12.dll only exists on Windows 10 systems.

You cannot QueryInterface a IDXIGDevice from a ID3D12Device, nor can you create a IDXGIDevice using D3D12CreateDevice. This is not supported for Direct3D 12. DXGI is strictly for dealing with adapters, outputs, and swap chains, not Direct3D devices.

• It has been my experience in fact that you indeed can D3D12CreateDevice with result S_OK using a device of type IDXIGDevice if you __uuidof(ID3D12Device) it instead of IID_PPV_ARGS() it. Which kinda forces it to a different type (which is why microsoft recommends only using the IDD_PPV_ARGS() for querying com interfaces instead of explicitly getting the RIID and passing the pointer to the device buffer pointer separately. I managed to fall into this by simply declaring the device of wrong type, IDXGIDevice and not ID3D12Device. Due to the similar name I just assumed ...cont – marshal craft Nov 14 '16 at 6:55
• cont...I was using an ID3D12Device. As I kept getting an E_nointerface from D3D12CreateDevice with IID_PPV_ARGS() I switched to __uuidof(). So to summarize if you use a ComPtr<IDXIGDevice> and essentially cast it to a ID3D12Device for the RIID, D3D12CreateDevice will return with S_OK. It's not till you attempt to get a command queue from it that it refuses. So while I could down vote your answer for being factually incorrect, as my seemingly valid path through this issue was deemed the same thoughtful or rather commentful criticism; I will not bother. – marshal craft Nov 14 '16 at 7:07
• If you are doing ComPtr<IDXIGDevice> device; D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), &device); then what you are getting back isn't a valid IDXGIDevice interface. Only the IUnknown interfaces are actually the same in those two interfaces. That's not actually valid COM code to be writing here, so I'm not surprised that you eventually hit something that failed. – Chuck Walbourn Nov 14 '16 at 8:17
• I guess the part of D3D12CreateDevice either doesn't or can't check the pointer's type, so assumes the type of the RIID. It probably just chooses the interface type to fill into the pointer based on the RIID. So it functionally works the same. It's not until the compiler takes a look at the header for a IDXGIDevice later on and realizes it "shouldn't" have a CreateCommandQueue() method member. At any rate it was a typo probably because I intuitively perceived the Dxgi.dll handles the adapter device creation and not D3d12.dll. Interesting. – marshal craft Nov 14 '16 at 9:05
• If you look at the actual signature of D3D12CreateDevice, the 4th parameter is void**. The IID_PPV_ARGS is not so much a recommendation as the only way to remotely make this type-safe. You are basically doing something like: MyClass* ptr = (MyClass*)( new TotallyUnrelatedClass )` – Chuck Walbourn Nov 14 '16 at 17:35