Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2017-06

Cannot trap divide by zero in xmm register

5 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Anthony Walter

I am having a problem with unrecoverable errors in external code, presumably generated by the video driver, crashing my programs. I cannot trap these errors with try..except blocks. Here is a capture of the assembler window with ** marking the line where the error occurs.

00007FFFEA79016F 4898 cltq
**00007FFFEA790171 f20f5e44c430 divsd 0x30(%rsp,%rax,8),%xmm0 00007FFFEA790177 f20f118424f8000000 movsd %xmm0,0xf8(%rsp) 00007FFFEA790180 f20f118424f0000000 movsd %xmm0,0xf0(%rsp) 00007FFFEA790189 f20f118424e8000000 movsd %xmm0,0xe8(%rsp)

In pascal code I am attempting to link a glsl program (part of OpenGL) when the uncatchable and unrecoverable error occurs.

*function* TShaderProgram.Link: Boolean;
*var*
  I: GLint;
  S: string;
*begin*
  *if* Flinked *then*
    Exit(False);
  *if* FAttachCount < 2 *then*
    Exit(False);
  FLinked := True;
  *// Sometimes the uncatchable error happens here*
  glLinkProgram(FHandle);
  glGetProgramiv(FHandle, GL_LINK_STATUS, @I);
  FValid := I = GL_TRUE;
  *if* *not* FValid *then*
  *begin*
    FErrorObject := Self;
    glGetProgramiv(FHandle, GL_INFO_LOG_LENGTH, @I);
    *if* I > 0 *then*
    *begin*
      SetLength(S, I);
      glGetProgramInfoLog(FHandle, I, @I, PChar(S));
    *end*
    *else*
      S := 'Unknown error';
    FErrorString := S;
  *end*;
*end*;

In this code I am attempting to link user defined glsl vertex and fragment shaders to generate a valid glsl program object. Sometimes either the vertex or fragment shader contains bad code, but it shouldn't bring down my entire pascal application. I've written and used these same shaders in c# using mono and I've never had them crash my mono applications. Is there some setting in fpc or in lazarus to handle these types of errors in the XMM registers gracefully?

To give you an idea of what I am doing, here is a screen recording of made earlier of these same shader programs running without crashing my application when using mono.

http://cache.getlazarus.org/videos/bare-csharp.mp4

Reply by email

Anthony Walter
to Anthony Walter

Some progress ... Since this is an OpenGL app I had been setting Set8087CW($133F) to prevent FPU errors from showing as exceptions. When I omit Set8087CW I get EDivByZero an exception, but my program is still in an unusable state.

Since this error occurs in the SSE XMM registers, I think I should also be using the SetSSECSR function. Does anyone have any details about how this function works in relation to XMM registers and rounding or divide by zero errors and how it could be applied in my situation?

Reply by email

Henry Vermaak
to Anthony Walter
Anthony Walter wrote 9 lines
Some progress ... Since this is an OpenGL app I had been setting Set8087CW($133F) to prevent FPU errors from showing as exceptions. When I omit Set8087CW I get EDivByZero an exception, but my program is still in an unusable state. Since this error occurs in the SSE XMM registers, I think I should also be using the SetSSECSR function. Does anyone have any details about how this function works in relation to XMM registers and rounding or divide by zero errors and how it could be applied in my situation?

I use this for all my programs that use C libraries:

{$if defined(cpui386) or defined(cpux86_64)}
  SetExceptionMask(GetExceptionMask + [exZeroDivide, exInvalidOp]);
{$ifend}

Works fine with libs like OpenCV, etc.

Henry

Reply by email

Henry Vermaak
to Henry Vermaak
Henry Vermaak wrote 18 lines
On Tue, Jun 20, 2017 at 10:53:32AM -0400, Anthony Walter wrote: > Some progress ... Since this is an OpenGL app I had been > setting Set8087CW($133F) to prevent FPU errors from showing as exceptions. > When I omit Set8087CW I get EDivByZero an exception, but my program is > still in an unusable state. > > Since this error occurs in the SSE XMM registers, I think I should also be > using the SetSSECSR function. Does anyone have any details about how this > function works in relation to XMM registers and rounding or divide by zero > errors and how it could be applied in my situation? I use this for all my programs that use C libraries: {$if defined(cpui386) or defined(cpux86_64)} SetExceptionMask(GetExceptionMask + [exZeroDivide, exInvalidOp]); {$ifend} Works fine with libs like OpenCV, etc.

Sorry, meant to add that this will also set the flags in MXCSR if you look at the implementation of SetExceptionMask().

Henry

Reply by email