Some computer configurations have multiple GPUs, e.g. gaming laptop with an Intel HD Graphics chip and a GeForce or Radeon chip. When enumerating through the available adapters on a computer, the Intel chip is the first one in most cases. However, I want to use the best adapter for my game. So I wrote the code below to create my swap chain:
protected void CreateDevice(Size clientSize, IntPtr outputHandle)
{
ProcessLogger.Instance.StartFunction(this, "CreateDevice");
// Set swap chain flags, DXGI format and default refresh rate.
_swapChainFlags = SharpDX.DXGI.SwapChainFlags.None;
_dxgiFormat = SharpDX.DXGI.Format.R8G8B8A8_UNorm;
SharpDX.DXGI.Rational refreshRate = new SharpDX.DXGI.Rational(60, 1);
// Get proper video adapter and create device and swap chain.
using (var factory = new SharpDX.DXGI.Factory1())
{
SharpDX.DXGI.Adapter adapter = GetAdapter(factory);
if (adapter != null)
{
ProcessLogger.Instance.Write(String.Format("Selected adapter: {0}", adapter.Description.Description));
// Get refresh rate.
refreshRate = GetRefreshRate(adapter, _dxgiFormat, refreshRate);
ProcessLogger.Instance.Write(String.Format("Selected refresh rate = {0}/{1} ({2})", refreshRate.Numerator, refreshRate.Denominator, refreshRate.Numerator / refreshRate.Denominator));
// Create Device and SwapChain
ProcessLogger.Instance.Write("Create device.");
_device = new SharpDX.Direct3D11.Device(adapter, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport, new SharpDX.Direct3D.FeatureLevel[]
{
SharpDX.Direct3D.FeatureLevel.Level_10_1
});
ProcessLogger.Instance.Write("Create swap chain.");
_swapChain = new SharpDX.DXGI.SwapChain(factory, _device, GetSwapChainDescription(clientSize, outputHandle, refreshRate));
ProcessLogger.Instance.Write("Store device context.");
_deviceContext = _device.ImmediateContext;
}
}
ProcessLogger.Instance.EndFunction(this, "CreateDevice");
}
For this function to work properly, I have to select the proper adapter in GetAdapter. Here is what it looks like:
private SharpDX.DXGI.Adapter GetAdapter(SharpDX.DXGI.Factory1 factory)
{
List<SharpDX.DXGI.Adapter> adapters = new List<SharpDX.DXGI.Adapter>();
for (int i = 0; i < factory.GetAdapterCount(); i++)
{
SharpDX.DXGI.Adapter adapter = factory.GetAdapter(i);
if (SharpDX.Direct3D11.Device.IsSupportedFeatureLevel(adapter, SharpDX.Direct3D.FeatureLevel.Level_10_1))
adapters.Add(adapter);
}
try
{
foreach (var adapter in adapters)
if (adapter.Description.Description != null && (adapter.Description.Description.Contains("GeForce") || adapter.Description.Description.Contains("Radeon")))
{
return adapter;
}
}
catch
{
}
return adapters.First();
}
So all I am doing is asking my Factory1 for a list of all adapters that support FeatureLevel 10.1 and search for a "GeForce" or "Radeon" one. Very simple and use that one.
This works like a charm. HOWEVER, there is one big problem: When I use this code in the Release build the game crashes when going to fullscreen using the code below.
public void SetFullscreenState(bool isFullscreen)
{
if (isFullscreen != _swapChain.IsFullScreen)
_swapChain.SetFullscreenState(isFullscreen, null);
}
The error code is DXGI_ERROR_UNSUPPORTED and after doing some research I found out, that this problem only happens for the Release build but not for the Debug build. The Debug build works like a charm. It also crashes only, if the selected adapter is not the first one in the list. So, if I use the first adapter (factory.GetAdapter(0)), it works! If I change my computer settings so that my GeForce is used as primary adapter for my game, it works.
It only does not work for the Release build, if the selected adapter is not the first adapter in the list and I can't figure out why... The problem is independent from the used screen or other running applications in a multi-windowed application. I already tested that.