GraphicsModeException when creating GLControl on Windows #42

Closed
repetier opened this Issue Jan 9, 2014 · 8 comments

2 participants

@repetier

This is a same issue as in issue#27 only for windows. On my old laptop with a NVIDEA graphics card creating a GLControl with anti-aliasing creates an Exception and Program stops. Same without anti-aliasing works fine. So I guess you need to do the mode relaxation trick you introduced in linux as well on windows. Not all drivers find the best mode on their own.

I tried also to catch the exception in the new GLControl(mode), which failed because of the lazy creation I think. Otherwise I could use a fallback on my own.

Some users seem to get even worse problems:

Problemsignatur:
Problemereignisname:    APPCRASH
Anwendungsname: RepetierHost.exe
Anwendungsversion:  1.0.0.0
Anwendungszeitstempel:  52cac230
Fehlermodulname:    ig4icd32.dll
Fehlermodulversion: 8.14.10.1930
Fehlermodulzeitstempel: 4aba6fc2
Ausnahmecode:   c0000005
Ausnahmeoffset: 0006605e
Betriebsystemversion:   6.1.7601.2.1.0.256.1
Gebietsschema-ID:   1031
Zusatzinformation 1:    0a9e
Zusatzinformation 2:    0a9e372d3b4ad19135b953a78882e789
Zusatzinformation 3:    0a9e
Zusatzinformation 4:    0a9e372d3b4ad19135b953a78882e789

This report was for 1.1beta4 and it seems to be a intel graphic card. OpenTK 1.0 worked well on the same computer, if that helps. Unfortunately I have no computer with that card on my own to verify, but quite some users seem to have:-( Also I do not understand much of these data, I guess you tried to use method not implemented in that driver?

@thefiddler

Thanks for the bug report.

My feeling is that these are two separate issues. Can you please post the exact exception message you are receiving on the Nvidia laptop, plus a debug.log from a debug build of OpenTK? It would be awesome if you could capture those using an up-to-date clone of opentk/develop, since that contains another improvement to the relaxation logic in WinGraphicsMode (fix for issue #39).

The Intel issue appears to be a driver crash. Without information on which method is crashing, it is difficult to say what is going wrong. Is this happening on startup or during execution?

@repetier

Ok, a new develop version is a bit too much, but i updated WinGraphicsMode to the latest version,which is where the source is anyway. Debugging mode 32bit,16 bit depth, 0 accumul,4 samples, 2 buffer returns in the second call
{Index: 0, Color: 32 (8888), Depth: 16, Stencil: 0, Samples: 0, Accum: 0 (0000), Buffers: 1, Stereo: False} = mode 0 from the ChoosePixelFormatARB method,while the first iteration used to create the first window handle used created_mode = created_mode ?? ChoosePixelFormatPFD(Device, mode, AccelerationType.ICD); and returned mode 1.

Then in SetGraphicsModePFD it throws this exception:
if (!Functions.SetPixelFormat(window.DeviceContext, (int)mode.Index.Value, ref pfd))
{
throw new GraphicsContextException(String.Format(
"Requested GraphicsMode not available. SetPixelFormat error: {0}",
Marshal.GetLastWin32Error()));

pfd is set with 0 on all fields,so I guess it is a invalid mode (0). In the first pfd iteration over all modes, mode started with 1!

I think the error occurs here in ChoosePixelFormatARB

            if (Wgl.Arb.ChoosePixelFormat(device, attributes.ToArray(), null, format.Length, format, out count))
            {
                created_mode = DescribePixelFormatARB(device, format[0]);
            }

count is returned as 0, so using the not set result as mode is invalid. Fixing it like this
if (Wgl.Arb.ChoosePixelFormat(device, attributes.ToArray(), null, format.Length, format, out count))
{
if(count>0)
created_mode = DescribePixelFormatARB(device, format[0]);
else
Debug.Print("[WGL] ChoosePixelFormatARB failed with {0}", Marshal.GetLastWin32Error());
}

worked for that part.

Drawback is that WinGLContext

    public override void SwapBuffers()
    {
        if (!Functions.SwapBuffers(DeviceContext))
            throw new GraphicsContextException(String.Format(
                "Failed to swap buffers for context {0} current. Error: {1}", this, Marshal.GetLastWin32Error()));
    }

now throws exceptions, because the selected mode did not support double buffering.
When I call it without samples enabled the ARB method returns mode 5 which also has double buffering.

@thefiddler

Thanks for the analysis, this throws some light into the issue. There is a high chance this and #45 are related.

On to the content:

if (!Functions.SetPixelFormat(window.DeviceContext, (int)mode.Index.Value, ref pfd))
{
throw new GraphicsContextException(String.Format(
"Requested GraphicsMode not available. SetPixelFormat error: {0}",
Marshal.GetLastWin32Error()));
pfd is set with 0 on all fields,so I guess it is a invalid mode (0).

What does Marshal.GetLastWin32Error() return here?

MSDN is somewhat unclear, but SetPixelFormat hints that we might need to fill pfd with DescribePixelFormat before passing it to SetPixelFormat.

if(count>0)
    created_mode = DescribePixelFormatARB(device, format[0]);
else
    Debug.Print("[WGL] ChoosePixelFormatARB failed with {0}", Marshal.GetLastWin32Error());

Good catch!

When I call it without samples enabled the ARB method returns mode 5 which also has double buffering.

And now I know how to reproduce the issue. Thanks, will try this in a moment.

Edit: I can reproduce if I set AA to an obscene value (e.g. 64). Investigating.

@repetier

Small update.
ChoosePixelFormatPFD doesnot honor double buffer when searching for the best mode. Adding

            if((pfd.Flags & PixelFormatDescriptorFlags.DOUBLEBUFFER)==0 && mode.Buffers>1)
                dist += 1000;

returned also mode 5 for me, which is the one with double buffers. I think high penalty for double buffer is ok, because SwapBuffers throws an exception when no double buffers are present and who demands double buffer will use that function. It also doesnot test for anti-alias samples, but I can live with that for those not supporting it through ARB function. At least it runs.

I think yout SetPixelFormat usage is ok. It only happened when it was called with mode 0, becaus eno mode was returned. In any case, called with wrong mode makes it return error code 87.

@thefiddler thefiddler added a commit that referenced this issue Jan 10, 2014
@thefiddler thefiddler [Win] More robust WGL extension detection
Affects issue #42 and issue #45
ef5aedb
@thefiddler thefiddler added a commit that referenced this issue Jan 10, 2014
@thefiddler thefiddler [Win] More robust pixel format selection
This patch adds more robust checks for WGL_ARB_pixel_format and
WGL_ARB_multisample before using the relevant extensions, and adds
checks whether Wgl.Arb.ChoosePixelFormat() returns a valid pixel format
before trying to use it (thanks to Repetier for catching this edge
case.)

Additionally, the ChoosePixelFormatPFD code-path now heavily penalizes
single-buffered modes when the user requests a double-buffered mode.

Affects issues #42 and #45
bdfcf43
@thefiddler

Another good catch, both changes are now committed. According to WGL_ARB_pixel_format,

 Application programmers must check to see if a particular extension is
     supported before using any pixel format attributes associated with the
     extension. For example, if WGL_ARB_pbuffer is not supported then it is
     an error to specify WGL_DRAW_TO_PBUFFER_ARB in the attribute list to
     wglGetPixelFormatAttrib*vARB or wglChoosePixelFormatARB.

OpenTK will now explicitly check for WGL_ARB_pixel_format and WGL_ARB_multisample before using these extensions. This might help with the Intel crash.

Edit: the final missing piece is a minimization strategy in ChoosePixelFormatARB to match X11GraphicsMode. In particular, it would be nice to fall back to the maximum supported AA level if the user specifies an unsupported level.

@repetier

Installed the latest development version now and asked in my forum, if the problems disappeared. They definitely did for my laptop, the only open question are Intel graphic card users. I will report back, when I get some responses.

@thefiddler

I'm assuming that this issue has been resolved, please report a new issue in case of crashes during context construction.

@thefiddler thefiddler closed this Mar 11, 2014
@repetier

I switched back to the old OpenTK version to get rid of customer complains. I think it was working on some Intel cards but not all like the old version. At least my intel graphic card worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment