I'm filling a window with a blank swap chain that's being handled by DirectX 12. While fooling a round a bit with Explicit Multi-Adapter, I came across this weird behaviour...
As shown in pretty much all DX12 demo code in existence so far, I loop through all DXGI adapters that I get using IDXGIFactory4::EnumAdapters1()
to find the most suitable (or in my case every) adapter at D3D_FEATURE_LEVEL_11_0
or higher. And as shown in the demos, I discard all adapters that have the DXGI_ADAPTER_FLAG_SOFTWARE
like this:
if ((adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) != FALSE)
continue; // Check the next adapter.
In my implementation I then dump all compatible adapters into a std::vector
to be used later.
If I use a breakpoint to check how everything looks at runtime, I notice my adapter list only contains one adapter after the loop has exited, which is not what I would expect, as I have both an NVIDIA GeForce GT 650M and an Intel HD Graphics 4000.
By breaking during the loop and checking the DXGI_ADAPTER_DESC2
structure for each adapter, I find that the one I get is indeed the GT 650M, so that means my integrated graphics is identifying itself as a software adapter.
This is plausible on its own, but if you look at a picture of an Ivy Bridge die (which is what I have) you see a big area cordoned off as "Processor Graphics", which Intel themselves define like this: "Processor graphics refer to graphics that are physically in the processor package or integrated into the processor silicon." That just screams "hardware adapter" at me.
If I remove the above code block I do indeed get two adapters in my list, but the second one identifies itself as "Microsoft Basic Render Driver" and gives a vendor ID of 0x1414
, while Google says that Intel usually returns 0x8086
as its ID. This list doesn't even mention the owner of 0x1414
.
And, to make things even more confusing, if I check the Information Center in my Intel HD Graphics Control Panel it says it has a vendor ID of 0x8086
!
Before anyone asks: Yes, my drivers should be up-to-date; I updated them as soon as I noticed this. Strangely though, DxDiag gives me an incorrect driver date for the integrated graphics, but does the same (though slightly closer to the truth) for the GT 650M. The discrete GPU driver is of WDDM 2.0, while the integrated graphics driver is of WDDM 1.3, which might be relevant, because I think it should be of 2.0 too. (Might the update have failed?)
The primary reason for the if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
filter is to avoid selecting the Microsoft Basic Render Driver. This uses the WARP11 software device which does not support DirectX 12.
WARP11 is supported in all versions of Windows with DirectX 11. WARP12 is currently a developer only device (i.e. "Graphics Tools" optional feature-on-demand is installed).
It's probably a bug if your discrete part is returning true for this flag. It might be a bug in your code, a driver bug, or some strange side-effect of Optimus-style selection. WARP / MBR is really the only thing that is expected to return DXGI_ADAPTER_FLAG_SOFTWARE
.
You can also exclude MBR via a if ( ( adapterDesc.VendorId == 0x1414 ) && ( adapterDesc.DeviceId == 0x8c ) )
test for well-known VendorID/DeviceID, but I suggest digging your code to understand why you are incorrectly getting DXGI_ADAPTER_FLAG_SOFTWARE
returned for hardware devices.