foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters) { System.Diagnostics.Debug.Write("Adaptor Name: "); System.Diagnostics.Debug.WriteLine(adapter.Description); System.Diagnostics.Debug.WriteLine(adapter.DeviceName); GraphicsDeviceCapabilities caps = adapter.GetCapabilities(DeviceType.Hardware); if (caps.MaxPixelShaderProfile < ShaderProfile.PS_2_0) { System.Diagnostics.Debug.WriteLine("This adapter doesn't support PS 2.0"); } } using (Game1 game = new Game1()) { game.Run(); }
In my little bit of reading about XNA to this point, I knew that XNA requires Pixel Shader 1.1 support as a minimum (although, a reference rasterizer is available, but not well documented). To verify that my cards met this requirement, I inserted code to interrogate each adapter on my system, which only pushed the "unexpected error" earlier in the code.
I did some further research, and GeForce 6200 cards implement the Pixel Shader 3.0 spec, so I'm comfortably within the required hardware for XNA.
Reading the documentation for GraphicsAdapter::GetCapabilities, there's no mention of raising an InvalidOperationException.
I fired up the "DirectX Caps Viewer", which is part of the DirectX
9.0c SDK, and looked at "DirectX Graphics Adapters/NVIDIA GeForce 6200
TurboCache(TM)/D3D Device Types" for all three adapters. Two out of
the three adapters had HAL and Reference devices, the third one just
had a reference device. Six hours later, it occurred to me to check
the hardware acceleration settings for that device:
Workaround: It's troublesome that the very code that is supplied to check the capabilities of hardware fails, depending on the configuration of that hardware. If you're getting this exception, perhaps you can trap it and provide useful feedback to the users. I'm worried, though, because the exception is so general. It may well be raised by other undocumented failure cases, making the feedback you provide only marginally useful.
Using GraphicsAdapter::CheckDeviceType seems marginally helpful:
foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters) { System.Diagnostics.Debug.Write("Adaptor Name: "); System.Diagnostics.Debug.WriteLine(adapter.Description); System.Diagnostics.Debug.WriteLine(adapter.DeviceName); SurfaceFormat curFormat = adapter.CurrentDisplayMode.Format; if (!adapter.CheckDeviceType(DeviceType.Hardware, curFormat, curFormat, false)) { System.Diagnostics.Debug.WriteLine("This adapter doesn't have hardware support"); } else { GraphicsDeviceCapabilities caps = adapter.GetCapabilities(DeviceType.Hardware); if (caps.MaxPixelShaderProfile < ShaderProfile.PS_2_0) { System.Diagnostics.Debug.WriteLine("This adapter doesn't support PS 2.0"); } } } using (Game1 game = new Game1()) { game.Run(); }In it, I check to see if the device has hardware acceleration. This isn't sufficient to fix the problem, as GraphicsDeviceManager doesn't make this check in FindBestPlatformDevice, which is called within Game.Run().
To really fix this problem, it seems like you'd want to subclass off of GraphicsDeviceManager, and discard non-hardware-accelerated devices in your own implementation of FindBestPlatformDevice. (This would probably be similar to the code in the "How To: Restrict Graphics Devices to Widescreen Aspect Ratios in Full-Screen Mode" sample.)