SDL2-for-Pascal icon indicating copy to clipboard operation
SDL2-for-Pascal copied to clipboard

SDL software renderer fails with Floating Point Exception

Open bunnylin opened this issue 2 years ago • 4 comments

This is mostly for visibility - I'm not sure where this would be best fixed.

It seems any SDL application compiled with Pascal will crash if trying to use software renderer video output, on Linux. To verify, run any SDL application with the environment variable LIBGL_ALWAYS_SOFTWARE=1 set. The failure happens either immediately on SDL_InitSubSystem(SDL_INIT_VIDEO), or when calling SDL_CreateRenderer. The error that appears can be EInvalidOp: Invalid floating point operation or EDivByZero: Division by zero depending on environment.

Doing this through GDB, I got this callstack pointing at the LLVMpipe software rasterizer:

lp_build_tgsi_info () from /usr/lib64/dri/swrast_dri.so
llvmpipe_create_fs_state () from /usr/lib64/dri/swrast_dri.so
ureg_create_shader () from /usr/lib64/dri/swrast_dri.so
util_make_fragment_tex_shader_writemask () from /usr/lib64/dri/swrast_dri.so
util_make_fragment_tex_shader () from /usr/lib64/dri/swrast_dri.so
blitter_get_fs_texfetch_col () from /usr/lib64/dri/swrast_dri.so
util_blitter_cache_all_shaders () from /usr/lib64/dri/swrast_dri.so
llvmpipe_create_context () from /usr/lib64/dri/swrast_dri.so
st_api_create_context () from /usr/lib64/dri/swrast_dri.so
dri_create_context () from /usr/lib64/dri/swrast_dri.so
driCreateContextAttribs () from /usr/lib64/dri/swrast_dri.so
drisw_create_context_attribs () from /lib64/libGLX_mesa.so.0
dri_common_create_context () from /lib64/libGLX_mesa.so.0
CreateContext () from /lib64/libGLX_mesa.so.0
glXCreateContext () from /lib64/libGLX_mesa.so.0
glXCreateContext () from /lib64/libGLX.so.0
X11_GL_LoadLibrary.part.0 () from /lib64/libSDL2-2.0.so.0

So it's a problem in Mesa. This doesn't affect Pascal/SDL programs on Windows since users don't normally run Mesa there. An internet search turned up this bug: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3096

They say the FPE should normally not be enabled in the first place, and the caller should just disable the exception mode. A commenter notes that the affected software was made with Delphi, which suggests to me that Free Pascal and Delphi are both deliberately keeping this FPE enabled (and are unlikely to change that because it would break compatibility).

As a workaround, it's simple to disable the exception by applying a mask, via the Math unit:

uses Math, SDL2;
var m : TFPUExceptionMask;
        window : PSDL_Window;
        renderer : PSDL_Renderer;
begin
        m := GetExceptionMask;
        include(m, exInvalidOp);
        SetExceptionMask(m); // <-- comment out this and it breaks again

        writeln(SDL_InitSubSystem(SDL_INIT_VIDEO));
        window := SDL_CreateWindow(NIL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                640, 400, SDL_WINDOW_SHOWN);
        if window = NIL then writeln('failed to create window: ' + SDL_GetError);
        renderer := SDL_CreateRenderer(window, -1, 0);
        if renderer = NIL then writeln('failed to get renderer: ' + SDL_GetError);
        writeln('no crash, all ok!');
end.

bunnylin avatar May 29 '22 21:05 bunnylin