Résolution du blocage en plein écran¶
Statut : Résolu Plateformes affectées : NVIDIA (confirmé) ; Intel non affecté
Problème¶
Lors de la bascule en plein écran via la touche F, l'application se bloquait de manière aléatoire sur les GPU NVIDIA. L'application devenait non réactive, nécessitant une terminaison forcée.
Analyse de la cause¶
Le blocage se produisait parce que glfwSetWindowMonitor() était appelé depuis le callback framebuffer_size_callback pendant qu'une opération GPU était en cours. Avec les pilotes NVIDIA, cela provoquait une condition de course entre :
1. Le thread GLFW gérant le changement de mode
2. Le pipeline GPU encore en train d'exécuter des commandes en attente
Solution¶
La correction utilise un modèle de redimensionnement différé en deux parties :
1. Drapeaux de redimensionnement différé¶
Au lieu d'appeler directement postprocess_resize depuis le callback, on lève un drapeau :
// Dans framebuffer_size_callback
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
App* app = glfwGetWindowUserPointer(window);
app->resize_pending = 1;
app->pending_width = width;
app->pending_height = height;
}
2. Drainage GPU avant la bascule¶
Dans app_toggle_fullscreen(), on appelle maintenant glFinish() avant d'invoquer glfwSetWindowMonitor(). Cela garantit que le pipeline GPU est entièrement vidé et que toutes les commandes en attente (clôtures, transferts PBO, échanges) sont terminées avant que le pilote tente le changement de mode.
3. Traitement dans la boucle principale¶
Le travail lourd réel (postprocess_resize) est déplacé au début de l'image suivante dans app_run, hors du contexte de callback GLFW.
// Dans la boucle while de app_run()
glfwPollEvents();
if (app->resize_pending) {
postprocess_resize(&app->postprocess, app->pending_width, app->pending_height);
app->resize_pending = 0;
}
Tests de stress¶
Un test de stress dédié a été créé pour vérifier ce correctif : scripts/test_stress_fullscreen.sh.
Fonctionnement¶
- Utilise
xdotoolpour envoyer des frappes 'F' rapidement (intervalles de 10 ms à 50 ms par exemple). - Surveille la sortie du journal de l'application plutôt que la visibilité de la fenêtre. Une application bloquée peut avoir une fenêtre visible mais arrêtera de journaliser « Switched to fullscreen/windowed ».
- Si le message de journal attendu n'apparaît pas dans les 5 secondes, un blocage est détecté, une trace de pile GDB complète de tous les threads est capturée, et l'application est terminée.
Exécution du test¶
Résumé des modifications¶
| Fichier | Modification |
|---|---|
include/app.h |
Ajout des champs resize_pending, pending_width, pending_height. |
src/app_input.c |
Mise à jour de framebuffer_size_callback pour utiliser des drapeaux ; ajout de glFinish() à la bascule. |
src/app.c |
Ajout de la logique de traitement du redimensionnement différé et de l'initialisation d'état. |
Justfile |
Ajout de l'automatisation stress-fullscreen. |