SDL2-for-Pascal
SDL2-for-Pascal copied to clipboard
SDL software renderer fails with Floating Point Exception
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.