Jump to content
  • Advertisement
GalacticCrew

DX11 CreateSwapChain throws an exception

Recommended Posts

A player of my game contacted me, because the game crashes during start-up. After taking a look into log file he sent me, calling CreateSwapChain results in an exception as shown below.

HRESULT: [0x887A0001], Module: [SharpDX.DXGI], ApiCode: [DXGI_ERROR_INVALID_CALL/InvalidCall], Message: Unknown
   at SharpDX.Result.CheckError()
   at SharpDX.DXGI.Factory.CreateSwapChain(ComObject deviceRef, SwapChainDescription& descRef, SwapChain swapChainOut)
   at SharpDX.Direct3D11.Device.CreateWithSwapChain(Adapter adapter, DriverType driverType, DeviceCreationFlags flags, FeatureLevel[] featureLevels, SwapChainDescription swapChainDescription, Device& device, SwapChain& swapChain)
   at SharpDX.Direct3D11.Device.CreateWithSwapChain(DriverType driverType, DeviceCreationFlags flags, SwapChainDescription swapChainDescription, Device& device, SwapChain& swapChain)

In order to investigate this player's problem, I created a test application that looks like this:

class Program
    {
        static void Main(string[] args)
        {
            Helper.UserInfo userInfo = new Helper.UserInfo(true);

            Console.WriteLine("Checking adapters.");
            using (var factory = new SharpDX.DXGI.Factory1())
            {
                for (int i = 0; i < factory.GetAdapterCount(); i++)
                {
                    SharpDX.DXGI.Adapter adapter = factory.GetAdapter(i);

                    Console.WriteLine("\tAdapter {0}: {1}", i, adapter.Description.Description);

                    bool supportsLevel10_1 = SharpDX.Direct3D11.Device.IsSupportedFeatureLevel(adapter, SharpDX.Direct3D.FeatureLevel.Level_10_1);
                    Console.WriteLine("\t\tSupport for Level_10_1? {0}!", supportsLevel10_1);

                    Console.WriteLine("\t\tCreate refresh rate (60).");
                    var refreshRate = new SharpDX.DXGI.Rational(60, 1);

                    Console.WriteLine("\t\tCreate mode description.");
                    var modeDescription = new SharpDX.DXGI.ModeDescription(0, 0, refreshRate, SharpDX.DXGI.Format.R8G8B8A8_UNorm);

                    Console.WriteLine("\t\tCreate sample description.");
                    var sampleDescription = new SharpDX.DXGI.SampleDescription(1, 0);

                    Console.WriteLine("\t\tCreate swap chain description.");
                    var desc = new SharpDX.DXGI.SwapChainDescription()
                    {
                        // Numbers of back buffers to use on the SwapChain
                        BufferCount = 1,

                        ModeDescription = modeDescription,

                        // Do we want to use a windowed mode?
                        IsWindowed = true,

                        Flags = SharpDX.DXGI.SwapChainFlags.None,

                        OutputHandle = Process.GetCurrentProcess().MainWindowHandle,

                        // Cout in 'SampleDescription' means the level of anti-aliasing (from 1 to usually 4)
                        SampleDescription = sampleDescription,
                        SwapEffect = SharpDX.DXGI.SwapEffect.Discard,

                        // DXGI_USAGE_RENDER_TARGET_OUTPUT: This value is used when you wish to draw graphics into the back buffer.
                        Usage = SharpDX.DXGI.Usage.RenderTargetOutput
                    };

                    try
                    {
                        Console.WriteLine("\t\tCreate device (Run 1).");
                        SharpDX.Direct3D11.Device device = new SharpDX.Direct3D11.Device(adapter, SharpDX.Direct3D11.DeviceCreationFlags.None, new SharpDX.Direct3D.FeatureLevel[]
                        {
                            SharpDX.Direct3D.FeatureLevel.Level_10_1
                        });

                        Console.WriteLine("\t\tCreate swap chain (Run 1).");
                        SharpDX.DXGI.SwapChain swapChain = new SharpDX.DXGI.SwapChain(factory, device, desc);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("EXCEPTION: {0}", e.Message);
                    }

                    try
                    {
                        Console.WriteLine("\t\tCreate device (Run 2).");
                        SharpDX.Direct3D11.Device device = new SharpDX.Direct3D11.Device(adapter, SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport, new SharpDX.Direct3D.FeatureLevel[]
                        {
                            SharpDX.Direct3D.FeatureLevel.Level_10_1
                        });

                        Console.WriteLine("\t\tCreate swap chain (Run 2).");
                        SharpDX.DXGI.SwapChain swapChain = new SharpDX.DXGI.SwapChain(factory, device, desc);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("EXCEPTION: {0}", e.Message);
                    }

                    try
                    {
                        Console.WriteLine("\t\tCreate device (Run 3).");
                        SharpDX.Direct3D11.Device device = new SharpDX.Direct3D11.Device(adapter);

                        Console.WriteLine("\t\tCreate swap chain (Run 3).");
                        SharpDX.DXGI.SwapChain swapChain = new SharpDX.DXGI.SwapChain(factory, device, desc);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("EXCEPTION: {0}", e.Message);
                    }
                }
            }

            Console.WriteLine("FIN.");
            Console.ReadLine();
        }
    }

In the beginning, I am collecting information about the computer (processor, GPU, .NET Framework version, etc.). The rest should explain itself. I sent him the application and in all three cases, creating the swap chain fails with the same exception.

In this test program, I included all solutions that worked for other users. For example, AlexandreMutel said in this forum thread, that device and swap chain need to share the same factory. I did that in my program. So using different factories is not a problem in my case. Laurent Couvidou said here:

Quote

This typically happens when calling a D3D function with an invalid parameter (e.g. a NULL pointer where not permitted). [...] You need to check one by one the parameters you provide to this function, especially in this case you need to check that the present parameters you provide are correct

The player has Windows 7 with .NET Framework 4.6.1, which is good enough to run my test application or game which use .NET Framework 4.5.2. The graphics cards (Radeon HD 6700 Series) is also good enough to run the application. In my test application, I also checked, if Feature Level 10_1 is supported, which is the minimum requirement for my game. A refresh rate of 60 Hz should also be no problem. Therefore, I think the parameters are fine. The remaining calls are just three different ways to create a device and a swap chain for the adapter. All of them throw an exception when creating the swap chain.

There are also 

" rel="external">Battlefield 3 players who had problems with running BF3. As it turned out, BF3 had some issue with Windows region settings. But I believe that's not a problem in my case. There were also compatibility issues in Fallout 4, but my game runs on many other Windows 7 PCs without any problems.

Do you have any idea what's wrong? I already have a lot of players that play my game without any issues, so it's not a general problem. I really want to help this player, but I currently can't find a solution.

Share this post


Link to post
Share on other sites
Advertisement

IIRC numBuffers=1 means you only have a front buffer with no back buffer. Try setting that to two.

You also really shouldn't hard code a 60Hz refresh rate. There's a lot of monitors that can't do 60Hz (high end gaming monitors sometimes do 50 or 72, but not 60). You should either enumerate the supported modes and pick one, or there's a value that means "pick one for me" (maybe 0? Check the docs). 

Share this post


Link to post
Share on other sites

Yeah, backbuffer should at least be 2 and no refresh hardcoded.

 

Another common source of crash is all the crappy hookup like steam, evga perf tools, …

 

Best way to tell would be a mini dump with callstack for that case.

Share this post


Link to post
Share on other sites

Unfortunately, the changes had no effect.

I use a default value of 60 Hz. Then I search for supported refresh rates for the current resolution. His console output says, the 60 Hz ist supported by his screen. I have absolutely no idea what's going wrong and the player gets impatient. :-/

                    Console.WriteLine("\t\tCreate refresh rate (60).");
                    SharpDX.DXGI.Rational refreshRate = new SharpDX.DXGI.Rational(60, 1);

                    Console.WriteLine("\t\tSelect supported refresh rate.");
                    for (int j = 0; j < adapter.Outputs.Length; j++)
                    {
                        SharpDX.DXGI.ModeDescription[] modeDescriptions = adapter.Outputs[j].GetDisplayModeList(dxgiFormat, SharpDX.DXGI.DisplayModeEnumerationFlags.Interlaced | SharpDX.DXGI.DisplayModeEnumerationFlags.Scaling);

                        bool isDone = false;
                        foreach (var description in modeDescriptions)
                            if (description.Width == userInfo.Resolution.Width && description.Height == userInfo.Resolution.Height)
                            {
                                refreshRate = description.RefreshRate;

                                Console.WriteLine("\t\t\tSelected refresh rate = {0}/{1} ({2})", description.RefreshRate.Numerator, description.RefreshRate.Denominator, description.RefreshRate.Numerator / description.RefreshRate.Denominator);

                                isDone = true;
                                break;
                            }

                        if (isDone)
                            break;
                    }

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!