mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-15 00:43:52 +00:00
fix(diagnostics): add render-phase crash markers and improve signal handling
Add signal-safe render-phase markers throughout GameScreen::render() and Application::render() so the crash handler can report which render call was active when a SIGSEGV occurs. The AMD RADV crash backtrace only shows 2 frames due to missing frame pointers, making it impossible to identify the actual crash site. Changes: - Add volatile g_crashRenderPhase marker updated before each major render call - Upgrade Linux signal handler to sigaction with SA_SIGINFO for faulting address - Set ImGui CheckVkResultFn to log silent Vulkan errors in ImGui backend - Enable -fno-omit-frame-pointer in all build configs (not just Debug/RelWithDebInfo)
This commit is contained in:
parent
b092bc2e90
commit
82267320b0
6 changed files with 104 additions and 29 deletions
|
|
@ -47,6 +47,11 @@
|
|||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
// Signal-safe render-phase marker — crash handler reads this to identify which
|
||||
// render call was active when a SIGSEGV occurs (backtrace is unreliable with
|
||||
// -fomit-frame-pointer).
|
||||
volatile const char* g_crashRenderPhase = "idle";
|
||||
#include <unordered_set>
|
||||
|
||||
namespace {
|
||||
|
|
@ -298,7 +303,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
// Process targeting input before UI windows
|
||||
processTargetInput(gameHandler);
|
||||
|
||||
// Player unit frame (top-left)
|
||||
g_crashRenderPhase = "playerFrame";
|
||||
renderPlayerFrame(gameHandler);
|
||||
|
||||
// Pet frame (below player frame, only when player has an active pet)
|
||||
|
|
@ -353,6 +358,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
}
|
||||
|
||||
// ---- New UI elements ----
|
||||
g_crashRenderPhase = "actionBar";
|
||||
actionBarPanel_.renderActionBar(gameHandler, settingsPanel_, chatPanel_,
|
||||
inventoryScreen, spellbookScreen, questLogScreen,
|
||||
[this](uint32_t id, pipeline::AssetManager* am) { return getSpellIcon(id, am); });
|
||||
|
|
@ -362,31 +368,43 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
actionBarPanel_.renderXpBar(gameHandler, settingsPanel_);
|
||||
actionBarPanel_.renderRepBar(gameHandler, settingsPanel_);
|
||||
auto spellIconFn = [this](uint32_t id, pipeline::AssetManager* am) { return getSpellIcon(id, am); };
|
||||
g_crashRenderPhase = "castBar";
|
||||
combatUI_.renderCastBar(gameHandler, spellIconFn);
|
||||
renderMirrorTimers(gameHandler);
|
||||
combatUI_.renderCooldownTracker(gameHandler, settingsPanel_, spellIconFn);
|
||||
renderQuestObjectiveTracker(gameHandler);
|
||||
g_crashRenderPhase = "nameplates";
|
||||
renderNameplates(gameHandler); // player names always shown; NPC plates gated by showNameplates_
|
||||
g_crashRenderPhase = "bgScore";
|
||||
combatUI_.renderBattlegroundScore(gameHandler);
|
||||
combatUI_.renderRaidWarningOverlay(gameHandler);
|
||||
combatUI_.renderCombatText(gameHandler);
|
||||
combatUI_.renderDPSMeter(gameHandler, settingsPanel_);
|
||||
g_crashRenderPhase = "durability";
|
||||
renderDurabilityWarning(gameHandler);
|
||||
renderUIErrors(gameHandler, ImGui::GetIO().DeltaTime);
|
||||
toastManager_.renderEarlyToasts(ImGui::GetIO().DeltaTime, gameHandler);
|
||||
g_crashRenderPhase = "partyFrames";
|
||||
if (socialPanel_.showRaidFrames_) {
|
||||
socialPanel_.renderPartyFrames(gameHandler, chatPanel_, spellIconFn);
|
||||
}
|
||||
g_crashRenderPhase = "bossFrames";
|
||||
socialPanel_.renderBossFrames(gameHandler, spellbookScreen, spellIconFn);
|
||||
g_crashRenderPhase = "dialogs";
|
||||
dialogManager_.renderDialogs(gameHandler, inventoryScreen, chatPanel_);
|
||||
g_crashRenderPhase = "guildRoster";
|
||||
socialPanel_.renderGuildRoster(gameHandler, chatPanel_);
|
||||
socialPanel_.renderSocialFrame(gameHandler, chatPanel_);
|
||||
g_crashRenderPhase = "buffBar";
|
||||
combatUI_.renderBuffBar(gameHandler, spellbookScreen, spellIconFn);
|
||||
g_crashRenderPhase = "lootWindow";
|
||||
windowManager_.renderLootWindow(gameHandler, inventoryScreen, chatPanel_);
|
||||
windowManager_.renderGossipWindow(gameHandler, chatPanel_);
|
||||
g_crashRenderPhase = "questWindows";
|
||||
windowManager_.renderQuestDetailsWindow(gameHandler, chatPanel_, inventoryScreen);
|
||||
windowManager_.renderQuestRequestItemsWindow(gameHandler, chatPanel_, inventoryScreen);
|
||||
windowManager_.renderQuestOfferRewardWindow(gameHandler, chatPanel_, inventoryScreen);
|
||||
g_crashRenderPhase = "vendorTrainer";
|
||||
windowManager_.renderVendorWindow(gameHandler, inventoryScreen, chatPanel_);
|
||||
windowManager_.renderTrainerWindow(gameHandler,
|
||||
[this](uint32_t id, pipeline::AssetManager* am) { return getSpellIcon(id, am); });
|
||||
|
|
@ -398,39 +416,48 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
windowManager_.renderBankWindow(gameHandler, inventoryScreen, chatPanel_);
|
||||
windowManager_.renderGuildBankWindow(gameHandler, inventoryScreen, chatPanel_);
|
||||
windowManager_.renderAuctionHouseWindow(gameHandler, inventoryScreen, chatPanel_);
|
||||
g_crashRenderPhase = "dungeonFinder";
|
||||
socialPanel_.renderDungeonFinderWindow(gameHandler, chatPanel_);
|
||||
windowManager_.renderInstanceLockouts(gameHandler);
|
||||
socialPanel_.renderWhoWindow(gameHandler, chatPanel_);
|
||||
g_crashRenderPhase = "combatLog";
|
||||
combatUI_.renderCombatLog(gameHandler, spellbookScreen);
|
||||
g_crashRenderPhase = "achievementSkills";
|
||||
windowManager_.renderAchievementWindow(gameHandler);
|
||||
windowManager_.renderSkillsWindow(gameHandler);
|
||||
windowManager_.renderTitlesWindow(gameHandler);
|
||||
windowManager_.renderEquipSetWindow(gameHandler);
|
||||
windowManager_.renderGmTicketWindow(gameHandler);
|
||||
g_crashRenderPhase = "inspectBook";
|
||||
socialPanel_.renderInspectWindow(gameHandler, inventoryScreen);
|
||||
windowManager_.renderBookWindow(gameHandler);
|
||||
g_crashRenderPhase = "threatBg";
|
||||
combatUI_.renderThreatWindow(gameHandler);
|
||||
combatUI_.renderBgScoreboard(gameHandler);
|
||||
g_crashRenderPhase = "minimap";
|
||||
if (showMinimap_) {
|
||||
renderMinimapMarkers(gameHandler);
|
||||
}
|
||||
g_crashRenderPhase = "deathLogout";
|
||||
windowManager_.renderLogoutCountdown(gameHandler);
|
||||
windowManager_.renderDeathScreen(gameHandler);
|
||||
windowManager_.renderReclaimCorpseButton(gameHandler);
|
||||
dialogManager_.renderLateDialogs(gameHandler);
|
||||
chatPanel_.renderBubbles(gameHandler);
|
||||
windowManager_.renderEscapeMenu(settingsPanel_);
|
||||
g_crashRenderPhase = "settings";
|
||||
settingsPanel_.renderSettingsWindow(inventoryScreen, chatPanel_, [this]() { saveSettings(); });
|
||||
toastManager_.renderLateToasts(gameHandler);
|
||||
g_crashRenderPhase = "weather";
|
||||
renderWeatherOverlay(gameHandler);
|
||||
|
||||
// World map (M key toggle handled inside)
|
||||
g_crashRenderPhase = "worldMap";
|
||||
renderWorldMap(gameHandler);
|
||||
|
||||
// Quest Log (L key toggle handled inside)
|
||||
g_crashRenderPhase = "questLog";
|
||||
questLogScreen.render(gameHandler, inventoryScreen);
|
||||
|
||||
// Spellbook (P key toggle handled inside)
|
||||
g_crashRenderPhase = "spellbook";
|
||||
spellbookScreen.render(gameHandler, services_.assetManager);
|
||||
|
||||
// Insert spell link into chat if player shift-clicked a spellbook entry
|
||||
|
|
@ -483,7 +510,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
|||
windowManager_.vendorBagsOpened_ = false;
|
||||
}
|
||||
|
||||
// Bags (B key toggle handled inside)
|
||||
g_crashRenderPhase = "inventory";
|
||||
inventoryScreen.setGameHandler(&gameHandler);
|
||||
inventoryScreen.render(gameHandler.getInventory(), gameHandler.getMoneyCopper());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue