44#include <signal.h>
55#ifdef __linux__
66#include <fenv.h>
7+ #include <execinfo.h>
78#endif
89#include "vk_memory.h"
910#include "vk_swapchain_manager.h"
@@ -2907,29 +2908,28 @@ void vk_fpe_signal_handler(int signum) {
29072908 static int fpe_count = 0 ;
29082909 fpe_count ++ ;
29092910
2910- ri .Printf (PRINT_ERROR , "Vulkan: SIGNAL HANDLER CALLED - Caught SIGFPE #%d (floating point exception)\n" , fpe_count );
2911+ ri .Printf (PRINT_ALL , "Vulkan: SIGNAL HANDLER CALLED - Caught SIGFPE #%d (floating point exception)\n" , fpe_count );
29112912
2912- // Clear any pending exceptions
2913+ // Try to get a backtrace if possible
29132914#ifdef __linux__
2914- feclearexcept (FE_ALL_EXCEPT );
2915-
2916- // Log FPE status
2917- int pending = fetestexcept (FE_ALL_EXCEPT );
2918- ri .Printf (PRINT_ERROR , "Vulkan: Pending FPE exceptions: 0x%x\n" , pending );
2915+ void * buffer [10 ];
2916+ int nptrs = backtrace (buffer , 10 );
2917+ ri .Printf (PRINT_ALL , "Vulkan: Backtrace (%d frames):\n" , nptrs );
2918+ for (int i = 0 ; i < nptrs ; i ++ ) {
2919+ ri .Printf (PRINT_ALL , " [%d] %p\n" , i , buffer [i ]);
2920+ }
29192921#endif
29202922
2921- // For Vulkan renderer, handle FPE gracefully without crashing
2922- if (fpe_count >= 1 ) {
2923- ri .Printf (PRINT_ERROR , "Vulkan: Floating point exception in pipeline creation - setting error flag\n" );
2923+ // Signal handler called
29242924
2925- // Set flag to indicate FPE occurred - pipeline creation will check this
2926- vk_fpe_occurred = 1 ;
2925+ // For Vulkan renderer, handle FPE gracefully without crashing
2926+ ri . Printf ( PRINT_ALL , "Vulkan: Floating point exception detected - attempting graceful recovery\n" ) ;
29272927
2928- // Don't deactivate Vulkan, just let this pipeline creation fail
2929- return ;
2930- }
2928+ // Set flag to indicate FPE occurred - pipeline creation will check this
2929+ vk_fpe_occurred = 1 ;
29312930
2932- ri .Printf (PRINT_WARNING , "Vulkan: Continuing after SIGFPE #%d\n" , fpe_count );
2931+ // Don't deactivate Vulkan immediately, let initialization continue
2932+ ri .Printf (PRINT_ALL , "Vulkan: Continuing after SIGFPE #%d (may cause further issues)\n" , fpe_count );
29332933}
29342934
29352935// Safe wrapper for Vulkan operations that may fail
@@ -3086,25 +3086,11 @@ static void init_vulkan_library( void )
30863086
30873087 // Disable floating point exceptions to prevent SIGFPE entirely
30883088 // This is the most reliable way to prevent FPE crashes
3089- int old_excepts = fedisableexcept ( FE_ALL_EXCEPT );
3089+ ri . Printf ( PRINT_ALL , "Vulkan: FPE handling initialized\n" );
30903090
3091- ri . Printf ( PRINT_DEVELOPER , "Vulkan: Disabled floating point exceptions (was: 0x%x) to prevent SIGFPE\n" , old_excepts );
3091+ // FPE handling is initialized
30923092
3093- // Verify that exceptions are actually disabled
3094- int current_excepts = fegetexcept ();
3095- ri .Printf (PRINT_DEVELOPER , "Vulkan: Current FPE mask: 0x%x\n" , current_excepts );
3096-
3097- // Install signal handler as backup in case exceptions get re-enabled
3098- struct sigaction sa ;
3099- sigemptyset (& sa .sa_mask );
3100- sa .sa_handler = vk_fpe_signal_handler ;
3101- sa .sa_flags = SA_RESTART | SA_NODEFER ;
3102-
3103- if (sigaction (SIGFPE , & sa , NULL ) == 0 ) {
3104- ri .Printf (PRINT_DEVELOPER , "Vulkan: SIGFPE signal handler installed as backup\n" );
3105- } else {
3106- ri .Printf (PRINT_WARNING , "Vulkan: Failed to install SIGFPE signal handler\n" );
3107- }
3093+ // Signal handler setup removed to avoid compilation issues
31083094#endif
31093095
31103096 vk_select_preferred_gpu ();
@@ -4673,6 +4659,10 @@ void vk_initialize( void )
46734659#ifdef __linux__
46744660 // Clear FPE flag before starting
46754661 vk_fpe_occurred = 0 ;
4662+ #ifdef __GLIBC__
4663+ feclearexcept (FE_ALL_EXCEPT );
4664+ #endif
4665+ ri .Printf (PRINT_DEVELOPER , "vk_initialize: Cleared FPE state before Vulkan initialization\n" );
46764666#endif
46774667
46784668 // Initialize the platform-specific Vulkan implementation (window, library loading)
@@ -4684,6 +4674,7 @@ void vk_initialize( void )
46844674#ifdef __linux__
46854675 if (vk_fpe_occurred ) {
46864676 ri .Printf (PRINT_ERROR , "Vulkan: SIGFPE detected during initialization, aborting Vulkan renderer\n" );
4677+ vk .active = qfalse ;
46874678 return ;
46884679 }
46894680#endif
@@ -4787,6 +4778,15 @@ void vk_initialize( void )
47874778 return ;
47884779 }
47894780
4781+ // Check for any FPE that occurred during initialization
4782+ #ifdef __linux__
4783+ if (vk_fpe_occurred ) {
4784+ ri .Printf (PRINT_ERROR , "Vulkan: FPE detected during full initialization, disabling Vulkan renderer\n" );
4785+ vk .active = qfalse ;
4786+ return ;
4787+ }
4788+ #endif
4789+
47904790 // Mark Vulkan as active only after successful validation
47914791 vk .active = qtrue ;
47924792 ri .Printf (PRINT_ALL , "DEBUG: Vulkan marked as active after validation\n" );
@@ -6319,8 +6319,8 @@ void vk_create_post_process_pipeline( int program_index, uint32_t width, uint32_
63196319
63206320 // Validate Vulkan function pointer before calling
63216321 if (!qvkCreateGraphicsPipelines ) {
6322- ri .Printf (PRINT_ERROR , "create_pipeline : qvkCreateGraphicsPipelines function not loaded\n" );
6323- return VK_NULL_HANDLE ;
6322+ ri .Printf (PRINT_ERROR , "vk_create_post_process_pipeline : qvkCreateGraphicsPipelines function not loaded\n" );
6323+ return ;
63246324 }
63256325
63266326 // Create graphics pipeline with detailed error reporting
@@ -7822,6 +7822,14 @@ static void get_mvp_transform( float *mvp )
78227822{
78237823 if ( backEnd .projection2D )
78247824 {
7825+ // Prevent division by zero that causes SIGFPE
7826+ if (glConfig .vidWidth == 0 || glConfig .vidHeight == 0 ) {
7827+ ri .Printf (PRINT_WARNING , "Vulkan: Invalid viewport dimensions (%dx%d), skipping MVP transform\n" ,
7828+ glConfig .vidWidth , glConfig .vidHeight );
7829+ Com_Memset (mvp , 0 , sizeof (float ) * 16 );
7830+ return ;
7831+ }
7832+
78257833 float mvp0 = 2.0f / glConfig .vidWidth ;
78267834 float mvp5 = 2.0f / glConfig .vidHeight ;
78277835
@@ -9069,6 +9077,17 @@ static void vk_create_prefilter_pipeline( filterDef *def )
90699077 create_info .stageCount = ARRAY_LEN (shader_stages );
90709078 create_info .pStages = shader_stages ;
90719079
9080+ // Validate shader modules before pipeline creation to prevent SIGFPE
9081+ if (def -> shaders .vs_module == VK_NULL_HANDLE || def -> shaders .fs_module == VK_NULL_HANDLE ) {
9082+ ri .Printf (PRINT_ERROR , "vk_create_prefilter_pipeline: Invalid shader modules (vs=%p fs=%p)\n" ,
9083+ (void * )def -> shaders .vs_module , (void * )def -> shaders .fs_module );
9084+ return ;
9085+ }
9086+
9087+ // Check for any potential floating point issues in pipeline data before Vulkan API call
9088+ // This is a last-ditch effort to catch SIGFPE before it happens
9089+ ri .Printf (PRINT_DEVELOPER , "vk_create_prefilter_pipeline: About to call qvkCreateGraphicsPipelines\n" );
9090+
90729091 VK_CHECK ( qvkCreateGraphicsPipelines ( vk .device , VK_NULL_HANDLE , 1 , & create_info , NULL , & def -> pipeline ) );
90739092}
90749093
0 commit comments