PDA

View Full Version : AMD Catalyst 11.9 crashes with wglCreateContext



BionicBytes
10-10-2011, 01:14 AM
Having just upgraded my catalyst drivers from 11.1 to 11.9 I have noticed that non of my OpenGL development projects work.

The problem seems to be wglCreateContent because when I run my projects through a debugger, this is the function call which produces an exception.

Does anyone else have this issue? Is there a workaround?

As I understand it, you have to first create a 2.x glContext in order to establish which version of OpenGl the h/w supports. Then you are able to call the newer wglCreateContextAttributes.

here's the pertinent windows code:


h_RC := wglCreateContext(h_DC);

if (h_RC = 0) then
begin
glKillWnd;
MessageBox(0, 'Unable to create a legacy OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

// Makes the specified OpenGL rendering context the calling thread's current rendering context
if (not wglMakeCurrent(h_DC, h_RC)) then
begin
glKillWnd;
MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

//Now have Open GL context. Initilialise all the GL functions.
extgl_Initialize;


// modify current context - add a OpenGL 3.x rendering context
if supportedExtensions.WGL[WGL_ARB_create_context] then
begin
oldh_RC := h_RC;
if supportedExtensions.OpenGL.Major < 3 then h_RC := wglCreateContextAttribsARB(h_DC,0,@GLattribs30)
else begin
//try and create a context using the new API using the highest available GL version.
//OpenGL 3.1 does not support the extended profile mask settings...
if (supportedExtensions.OpenGL.Major = 3) AND (supportedExtensions.OpenGL.Minor = 1) then h_RC := wglCreateContextAttribsARB(h_DC,0,@GLattribs31)
else begin
if NOT SupportedExtensions.wgl[WGL_ARB_create_context_profile] then
begin
setlength (ContextArrtibs, 7);
ContextArrtibs[0] := WGL_CONTEXT_MAJOR_VERSION_ARB; ContextArrtibs[1] := supportedExtensions.OpenGL.Major;
ContextArrtibs[2] := WGL_CONTEXT_MINOR_VERSION_ARB; ContextArrtibs[3] := supportedExtensions.OpenGL.minor;
ContextArrtibs[4] := WGL_CONTEXT_FLAGS_ARB; ContextArrtibs[5] := 0;
ContextArrtibs[6] := 0; //terminator
end else
begin
setlength (ContextArrtibs, 9);
ContextArrtibs[0] := WGL_CONTEXT_MAJOR_VERSION_ARB; ContextArrtibs[1] := supportedExtensions.OpenGL.Major;
ContextArrtibs[2] := WGL_CONTEXT_MINOR_VERSION_ARB; ContextArrtibs[3] := supportedExtensions.OpenGL.minor;
ContextArrtibs[4] := WGL_CONTEXT_FLAGS_ARB; ContextArrtibs[5] := 0;
ContextArrtibs[6] := WGL_CONTEXT_PROFILE_MASK_ARB; ContextArrtibs[7] := WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
ContextArrtibs[8] := 0; //terminator
end;
end;

h_RC := wglCreateContextAttribsARB(h_DC,0,@ContextArrtibs[0]);
end;

if (h_RC = 0) then
begin
MessageBox(0, 'Unable to set attributes for an OpenGL 3.x rendering context', 'Error', MB_OK or MB_ICONERROR);
error := getLastError ();
case error of
0:MessageBox(0, 'No information about the error from wglCreateContextAttribsARB available.', 'Error', MB_OK or MB_ICONERROR);
ERROR_INVALID_VERSION_ARB:MessageBox(0, 'Invalid OpenGL version requested', 'Error', MB_OK or MB_ICONERROR);
ERROR_INVALID_PROFILE_ARB:MessageBox(0, 'Invalid OpenGL profile requested', 'Error', MB_OK or MB_ICONERROR);
end;

h_RC := oldh_RC;
end else
begin
//release old GL context
wglMakeCurrent(h_DC, 0);
wglDeleteContext(oldh_RC);
end;

_arts_
10-10-2011, 05:54 AM
What about a simple glut program, does it crash too ?

Did you also try a sample C code (might then be your language port of wgl that has a bug) ?


As I understand it, you have to first create a 2.x glContext in order to establish which version of OpenGl the h/w supports. Then you are able to call the newer wglCreateContextAttributes.

Creating a default (pre 3) context allows you to be able to retreive pointers from wgl extensions (ie wglCreateContextAttribsARB) so that you can create 3.x contexts, since it is impossible to retrive function pointers without a valid and made current context.

BionicBytes
10-10-2011, 06:47 AM
I don't and never have used glut.
I have been using the same open gl window initialisation code for 10 years now and only has to tweak it recently for the wglcreatecontextattribute extension which was introduced for GL3.

So I doubt that my language porting has an issue.
This crash has only happened since the driver update which points to a fundamental bug in the AMD driver.

_arts_
10-10-2011, 07:00 AM
This crash has only happened since the driver update which points to a fundamental bug in the AMD driver.

Well, you might be right, but having such a bug that makes a crash on context creation implies that ATI does not test their driver at all, which I highly doubt.

Dan Bartlett
10-10-2011, 07:43 AM
11.9 works okay for me, what are you doing prior to the code you showed? Are you doing anything like calling SetPixelFormat multiple times, or not choosing a pixel format that supports OpenGL. A re-download/re-install might help too, could just be a bad install.

BionicBytes
10-10-2011, 09:26 AM
I know, the implication is that ATI have not tested their code, but I can't see how/why it's failing now immediately after a driver upgrade (I upgraded becuase I wanted to play 'Rage'). That's not working either (different story) so I also upgraded again to AMD Cat 11.10 preview2 drivers.
Guess what....the wglCreateContext has been fixed!

Rage doesn't work still.

BionicBytes
10-10-2011, 09:27 AM
For those who are interested...here's my OpenGl create window/context code.

I don't think I'm doing anything odd here.



{------------------------------------------------}
{ Attaches a OpenGL rendering context to Window }
{-------------------------------------------------}
function TOpenGLWindow.glWnd(Width, Height : Integer; Fullscreen : Boolean; PixelDepth : Integer) : Boolean;
var
dmScreenSettings : DEVMODE; // Screen settings (fullscreen, etc...)
PixelFormat : GLuint; // Settings for the OpenGL rendering
// h_Instance : HINST; // Current instance
pfd : PIXELFORMATDESCRIPTOR; // Settings for the OpenGL window
myScreen: Trect;
i,error: integer;
ContextArrtibs: TintegerArray;
const
// OpenGL context examples:
GLattribs31_core: array [0..6] of integer = (WGL_CONTEXT_MAJOR_VERSION_ARB, 3,WGL_CONTEXT_MINOR_VERSION_ARB, 1, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,0);
GLattribs32: array [0..8] of integer = (WGL_CONTEXT_MAJOR_VERSION_ARB, 3,WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_FLAGS_ARB, 0,WGL_CONTEXT_PROFILE_MASK_ARB,WGL_CONTEXT_COMPATI BILITY_PROFILE_BIT_ARB, 0); //terminate with a Zero
GLattribs30: array [0..6] of integer = (WGL_CONTEXT_MAJOR_VERSION_ARB, 3,WGL_CONTEXT_MINOR_VERSION_ARB, 0,WGL_CONTEXT_FLAGS_ARB, 0, 0); //terminate with a Zero
GLattribs31: array [0..6] of integer = (WGL_CONTEXT_MAJOR_VERSION_ARB, 3,WGL_CONTEXT_MINOR_VERSION_ARB, 1,WGL_CONTEXT_FLAGS_ARB, 0, 0); //terminate with a Zero

begin
result := false;
// extgl_InitializeWGL; //need to call this before OpenGl init...becase of OpenGL 3.x context
// extgl_SetupWGL;


flags := 0;
SetWindowFlags;

if UseGLWindow then
begin
MakeGLWindow (fglFormw,fglFormh, fullscreen); //Create OpenGl Window

// h_Instance := GetModuleHandle(nil); //Grab An Instance For Our Window
// Change to fullscreen if so desired
fFullScreen := fullscreen;

if fFullscreen then
begin
EnumDisplaySettings(nil, ENUM_CURRENT_SETTINGS, DMsaved); // Save Current Display
// ZeroMemory(@DMSaved, SizeOf(DMSaved));
DMSaved.dmPelsWidth := screen.Width; // Window width
DMSaved.dmPelsHeight := screen.Height; // Window height
// ChangeDisplaySettings(DMSaved,CDS_TEST);


ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings));
with dmScreenSettings do begin // Set parameters for the screen setting
dmSize := SizeOf(dmScreenSettings);
dmPelsWidth := Width; // Window width
dmPelsHeight := Height; // Window height
dmBitsPerPel := PixelDepth; // Window color depth
dmDisplayFlags := 0; //DM_GRAYSCALE DM_INTERLACED
// dmDisplayFrequency := 60;
// dmFields := DM_DISPLAYFREQUENCY or DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFLAGS;
dmFields := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL or DM_DISPLAYFLAGS;
end;

// Try to change screen mode to fullscreen. CDS_FULLSCREEN = Remove START bar
if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL) then
begin
MessageBox(0, 'Unable to switch to fullscreen!', 'Error', MB_OK or MB_ICONERROR);
fFullscreen := False;
end;

end; {fullscreen}


// If we are not in fullscreen then
if NOT (fFullscreen) then ShowMouse (true) // Turn on in window mode
else ShowMouse (fShowCursor); // Turn off the cursor (gets in the way)

end {UseGlWindow}
else h_Wnd := GLhwnd; {user suplied window handle}

if h_Wnd = 0 then
begin
glKillWnd; // Undo all the settings we've changed
MessageBox(0, 'Unable to initialise window!', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

// Try to get a device context
h_DC := GetDC(h_wnd);
if (h_DC = 0) then
begin
glKillWnd;
MessageBox(0, 'Unable to get a device context!', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

// Settings for the OpenGL window
with pfd do
begin
nSize := SizeOf(PIXELFORMATDESCRIPTOR); // Size Of This Pixel Format Descriptor
nVersion := 1; // The version of this data structure
dwFlags := Flags;
iPixelType := PFD_TYPE_RGBA; // RGBA color format
cColorBits := PixelDepth; // OpenGL color depth
cRedBits := 0; // Number of red bitplanes
cRedShift := 0; // Shift count for red bitplanes
cGreenBits := 0; // Number of green bitplanes
cGreenShift := 0; // Shift count for green bitplanes
cBlueBits := 0; // Number of blue bitplanes
cBlueShift := 0; // Shift count for blue bitplanes
cAlphaBits := 0; // Not supported
cAlphaShift := 0; // Not supported
cAccumBits := 0; // No accumulation buffer
cAccumRedBits := 0; // Number of red bits in a-buffer
cAccumGreenBits := 0; // Number of green bits in a-buffer
cAccumBlueBits := 0; // Number of blue bits in a-buffer
cAccumAlphaBits := 0; // Number of alpha bits in a-buffer
cDepthBits := FDepthBits; // Specifies the depth of the depth buffer. (16-bits or 32-bits)
cStencilBits := 0; // Turn off stencil buffer
cAuxBuffers := 0; // Not supported
iLayerType := PFD_MAIN_PLANE; // Ignored
bReserved := 0; // Number of overlay and underlay planes
dwLayerMask := 0; // Ignored
dwVisibleMask := 0; // Transparent color of underlay plane
dwDamageMask := 0; // Ignored
end;

// If component's settings specifies that the accumulation buffer is enabled
// then set its depth (which enables it)
if FAccumBufferEnabled then
pfd.cAccumBits := FAccumBits;

// If component's settings specifies that the stencil buffer is enabled
// then set its depth (which enables it)
if FStencEnabled then
pfd.cStencilBits := FStencBits;


if not InitOpenGL (fGlLib,fGluLib) then
begin
MessageBox(0, 'Unable to initialise OpenGL library', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;


// Attempts to find the pixel format supported by a device context that is the best match to a given pixel format specification.
PixelFormat := ChoosePixelFormat(h_DC, @pfd);
if (PixelFormat = 0) then
begin
glKillWnd;
MessageBox(0, 'Unable to find a suitable pixel format', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

// Sets the specified device context's pixel format to the format specified by the PixelFormat.
//NB can only be set once!
if Not glPixelSet then
if (not SetPixelFormat(h_DC, PixelFormat, @pfd)) then
begin
glKillWnd;
MessageBox(0, 'Unable to set the pixel format', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

glPixelset := true;

h_RC := wglCreateContext(h_DC);

if (h_RC = 0) then
begin
glKillWnd;
MessageBox(0, 'Unable to create a legacy OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

// Makes the specified OpenGL rendering context the calling thread's current rendering context
if (not wglMakeCurrent(h_DC, h_RC)) then
begin
glKillWnd;
MessageBox(0, 'Unable to activate OpenGL rendering context', 'Error', MB_OK or MB_ICONERROR);
Result := False;
Exit;
end;

//Now have Open GL context. Initilialise all the GL functions.
extgl_Initialize;


// modify current context - add a OpenGL 3.x rendering context - not fully tested
if supportedExtensions.WGL[WGL_ARB_create_context] then
begin
oldh_RC := h_RC;
if supportedExtensions.OpenGL.Major < 3 then h_RC := wglCreateContextAttribsARB(h_DC,0,@GLattribs30)
else begin
//try and create a context using the new API using the highest available GL version.
//OpenGL 3.1 does not support the extended profile mask settings...
if (supportedExtensions.OpenGL.Major = 3) AND (supportedExtensions.OpenGL.Minor = 1) then h_RC := wglCreateContextAttribsARB(h_DC,0,@GLattribs31)
else begin
if NOT SupportedExtensions.wgl[WGL_ARB_create_context_profile] then
begin
setlength (ContextArrtibs, 7);
ContextArrtibs[0] := WGL_CONTEXT_MAJOR_VERSION_ARB; ContextArrtibs[1] := supportedExtensions.OpenGL.Major;
ContextArrtibs[2] := WGL_CONTEXT_MINOR_VERSION_ARB; ContextArrtibs[3] := supportedExtensions.OpenGL.minor;
ContextArrtibs[4] := WGL_CONTEXT_FLAGS_ARB; ContextArrtibs[5] := 0;
ContextArrtibs[6] := 0; //terminator
end else
begin
setlength (ContextArrtibs, 9);
ContextArrtibs[0] := WGL_CONTEXT_MAJOR_VERSION_ARB; ContextArrtibs[1] := supportedExtensions.OpenGL.Major;
ContextArrtibs[2] := WGL_CONTEXT_MINOR_VERSION_ARB; ContextArrtibs[3] := supportedExtensions.OpenGL.minor;
ContextArrtibs[4] := WGL_CONTEXT_FLAGS_ARB; ContextArrtibs[5] := 0;
ContextArrtibs[6] := WGL_CONTEXT_PROFILE_MASK_ARB; ContextArrtibs[7] := WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
ContextArrtibs[8] := 0; //terminator
end;
end;

h_RC := wglCreateContextAttribsARB(h_DC,0,@ContextArrtibs[0]);
end;

if (h_RC = 0) then
begin
MessageBox(0, 'Unable to set attributes for an OpenGL 3.x rendering context', 'Error', MB_OK or MB_ICONERROR);
error := getLastError ();
case error of
0:MessageBox(0, 'No information about the error from wglCreateContextAttribsARB available.', 'Error', MB_OK or MB_ICONERROR);
ERROR_INVALID_VERSION_ARB:MessageBox(0, 'Invalid OpenGL version requested', 'Error', MB_OK or MB_ICONERROR);
ERROR_INVALID_PROFILE_ARB:MessageBox(0, 'Invalid OpenGL profile requested', 'Error', MB_OK or MB_ICONERROR);
end;

h_RC := oldh_RC;
end else
begin
//release old GL context
wglMakeCurrent(h_DC, 0);
wglDeleteContext(oldh_RC);
end;

if (h_RC = 0) then
begin
glKillWnd;
Result := False;
Exit;
end;

//use new GL 3.x context
wglMakeCurrent(h_DC, h_RC); //use GL context
extgl_Initialize;
end;


//read back Pixel format to see what OpenGL has assigned
PixelFormat := GetPixelFormat(h_dc);
DescribePixelFormat(h_dc, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), runtime.screen.pfd);
frequestedPixelDepth := PixelDepth;
RunTime.Screen.ColorDepth := runtime.screen.pfd.cColorbits;
AUX_vars.JPG_ALPHA := 255; //All JPG have the same default alpha.


fglInit := true;
result := true;
exit;

// Call assinged initialization routine and resize routine
GetClientRect(h_Wnd, myScreen); // get screen dimensions
fWindowW := myScreen.right; // save initial screen size for later
fWindowH := myScreen.bottom;

glResizeWnd(fWindowW, fWindowH); //SetRunTimeScreen;

end;

Hongwei Li
10-11-2011, 06:30 AM
The program logic is right. People are doing the same to create 3.x context. Most of them use c though. Could you let me know which line throws the exception?

BionicBytes
10-12-2011, 02:29 PM
Thanks for your interest.
The exact line which fails is the first call to wglCreateContext.


glPixelset := true;

h_RC := wglCreateContext(h_DC);

Hongwei Li
10-13-2011, 09:12 PM
It is wired. I can't understand how can this line is culprit as it is the must-be-called function for every windows ogl program. If this function is buggy, everyone should have complained. I am wondering if the ogl binding has something wrong. Are you using pascal or something else? Sorry I don't know much about other languages. But anyway, I'll keep looking into this problem and make you happy hopefully. :-)

Dan Bartlett
10-14-2011, 01:19 AM
If you have declared these functions yourself, rather than using Delphi's built in (out of date) OpenGL headers, then are you using the right calling convention for these functions? (eg. stdcall on Win32)

BionicBytes
10-14-2011, 08:04 AM
Yes it's weired and yes I'm surprised noone else has mentioned it. There are some hit on Google however!
The code is Pascal Delphi and yes I have checked the function pointers over and over. Bare in mind that I have used the same code for nearly Ten years without incident (after all how often does wglCreateContext change)?

Anyway the issue resolved itself with your Cat 11.10 preview 2 drivers!
Something odd going on in your driver builds!

Richard Müller
10-20-2011, 06:46 AM
I have exactly the same problem. After the update to Catalyst 11.9, the wglCreateContext function fails in one of my applications. The system reports a division by zero exception. I am also a Delphi programmer and I use the dglOpenGL interface unit of the DGL-OpenGl2-Portteam. Not all of my applications are affected. Unfortunately I cannot see why one application fails and the other doesn’t fail. It must have to do with the order of the function calls in the initialization routine (i.e. getting device context, setting pixelformat).

BionicBytes
10-20-2011, 10:12 AM
If you have declared these functions yourself, rather than using Delphi's built in (out of date) OpenGL headers, then are you using the right calling convention for these functions? (eg. stdcall on Win32)

To answer your question: all OpenGL functions and extensions I have implemented my self (using stdcall) and I am not using any 3rd party OpenGL headers. All of these functions are known to work and have been for many years on both nVidia and AMD hardware. I only had a problem recently after switching driver version.....

Richard Müller
10-20-2011, 11:55 PM
I want to point to another strange problem I was confronted with a while ago and I think it could give us an idea what the source of the problem might be. After a call to wglCreateContext, where I tried to get a rendering Context for a bitmap, the function returned with a changed (destroyed) CPU control word. It seemed as if the CPU was in an MMX mode and all subsequent floating point operations failed after this call to wglCreateContext. To solve the problem, I changed the code and I push the CPU control word before the call and restore it after the call to wglCreateContext. But this is a very unsatisfactory solution, because it is obvious that there is a problem with the implementation of the wglCreateContext function in combination with ATI gpus. The problem didn’t arise when I used wglCreateContext in order to get a rendering context for a window, only rendering contexts for bitmaps were affected.

Could it be that the catalyst 11.9 implementation of wglCreateContext forgets to switch back the CPU from the MMX state, i.e. forgets to empties the MMX state with the EMMS instruction?

Dan Bartlett
10-21-2011, 08:31 AM
Ah, have you included the following code at initialization?


Set8087CW($133F);

see http://docwiki.embarcadero.com/VCL/XE2/en/System.Set8087CW

But why a floating point exception is happening on creating a context, I don't know.

I experienced a similar problem when calling a particular OpenCL function with AMD drivers. IIRC it was that it was dividing by zero + by default Delphi doesn't just ignore those errors, but Visual Studio does.

Richard Müller
10-24-2011, 07:07 AM
Thank you for the hint.

As we use the dglOpenGl interface unit, the FPU control word is set during the initialization of the dglOpenGl unit:

initialization

{$IFDEF CPU386}
Set8087CW($133F);
{$ENDIF}

But when I check the control word before the first call to wglCreateContext, I find it changed again. Some other initialization routines seem to change the FPU control word, too. This could explain why not all of our applications are affected by the error. Dependent on when the initialization of the dglOpenGl unit takes place, the FPU control word is possibly but not necessarily changed afterwards by other routines.

I feel not happy with the solution to disable all floating point exceptions. As we develop commercial software for a branch where the safe operation of the software is required, I would prefer to get the exceptions when they occur. An exception is a clear indicator to the user that something went wrong. If the user cannot see the exceptions, he will not be able to recognize that something went wrong! That is not good programing style, isn’t it?

BionicBytes
10-24-2011, 11:00 AM
Set8087CW($133F);
This is interesting and could explain why an exception is thrown for one set of drivers but not another.

I'll try and set the code in my engine and see what effect it has on the Cat 11.9 drivers which had the problem.

Richard Müller
10-24-2011, 11:37 PM
The forum has obviously come to the result that all floating point exceptions of the cpu have to be disabled when OpenGl is used within an application. What do you think, is this true?

Simon Arbon
10-25-2011, 10:56 PM
Although its not mentioned in any specification i can find, it seems to be quite common for OpenGL drivers to perform divisions by zero during their normal processing, so it is necisary to prevent this from raising an exception.
Every OpenGL.pas file i have back to Delphi 2 includes the Set8087CW($133f) command in its initialization.
There are posts on this forum going back to 2002 that recommend doing it.
My compiler documentation also mentions it:
It is recommended that you disable all floating-point exceptions when using OpenGL to render 3D graphics. To do this, call Set8087CW(0x133f) in your main form’s OnCreate event before calling any OpenGL functions.