To query the adapters from DXGI, we first need a DXGI factory object. This is done using the CreateDXGIFactory
function. In this case we use CreateDXGIFactory2
in order to be able to create an IDXGIFactory4
and create it with the debug flag set. Previous versions of this function call had restrictions in this regard.
result = CreateDXGIFactory2(
#if DEBUG_RENDERER
DXGI_CREATE_FACTORY_DEBUG,
#else
0,
#endif
&IID_IDXGIFactory4,
(void**)&renderer->dxgiFactory
);
if ( FAILED(result) )
RETURN_ERROR(-1, "CreateDXGIFactory2 failed (0x%08X)", result );
With the factory, we can now query adapters using the EnumAdapters1
function. Alternatively, we can query a WARP adapter using the EnumWarpAdapter
function. “WARP” stands for Windows Advanced Rasterization Platform, and is a full DirectX 11-compliant renderer implemented in software.
In the code below we query up to 4 hardware adapters, and insert the WARP adapter if it exists and we still have space for it. If we do not have any more space for the WARP adapter, we overwrite the last hardware adapter with the WARP device.
If we exclusively want to run with WARP or hardware, we can disable either ALLOW_HARDWARE_ADAPTERS
or ALLOW_WARP_ADAPTERS
.
IDXGIAdapter1* adapters[4] = { NULL };
uint32_t adapterCount = 0;
#if ALLOW_HARDWARE_ADAPTERS
while ( adapterCount < (STATIC_ARRAY_SIZE(adapters)-1) && renderer->dxgiFactory->lpVtbl->EnumAdapters1 ( renderer->dxgiFactory, adapterCount, &adapters[adapterCount] ) != DXGI_ERROR_NOT_FOUND )
{
adapterCount++;
}
#endif
#if ALLOW_WARP_ADAPTER
uint32_t warpIndex = RVM_MIN(adapterCount,STATIC_ARRAY_SIZE(adapters)-1);
if ( SUCCEEDED ( renderer->dxgiFactory->lpVtbl->EnumWarpAdapter ( renderer->dxgiFactory, &IID_IDXGIAdapter1, &(void*)adapters[warpIndex] ) ) )
{
adapterCount = warpIndex + 1;
}
#endif