fix(diagnostics): add sub-phase markers inside Renderer::beginFrame

AMD RADV crash is renderPhase=beginFrame with faultAddr=(nil) — a NULL
pointer dereference somewhere in the pre-pass chain. Add granular markers
(bf:ubo, bf:minimap, bf:worldmap, bf:preview, bf:shadow, bf:reflection,
bf:renderpass) to pinpoint the exact call.
This commit is contained in:
Kelsi 2026-04-03 20:28:37 -07:00
parent 82267320b0
commit 5778ba230d

View file

@ -1,3 +1,5 @@
extern volatile const char* g_crashRenderPhase;
#include "rendering/renderer.hpp" #include "rendering/renderer.hpp"
#include "rendering/camera.hpp" #include "rendering/camera.hpp"
#include "rendering/camera_controller.hpp" #include "rendering/camera_controller.hpp"
@ -836,6 +838,7 @@ void Renderer::beginFrame() {
if (postProcessPipeline_ && camera) postProcessPipeline_->applyJitter(camera.get()); if (postProcessPipeline_ && camera) postProcessPipeline_->applyJitter(camera.get());
// Update per-frame UBO with current camera/lighting state // Update per-frame UBO with current camera/lighting state
g_crashRenderPhase = "bf:ubo";
updatePerFrameUBO(); updatePerFrameUBO();
// GPU crash diagnostic: skip all pre-passes to isolate crash source // GPU crash diagnostic: skip all pre-passes to isolate crash source
@ -844,6 +847,7 @@ void Renderer::beginFrame() {
if (!skipPrePasses) { if (!skipPrePasses) {
// --- Off-screen pre-passes (before main render pass) --- // --- Off-screen pre-passes (before main render pass) ---
// Minimap composite (renders 3x3 tile grid into 768x768 render target) // Minimap composite (renders 3x3 tile grid into 768x768 render target)
g_crashRenderPhase = "bf:minimap";
if (minimap && minimap->isEnabled() && camera) { if (minimap && minimap->isEnabled() && camera) {
glm::vec3 minimapCenter = camera->getPosition(); glm::vec3 minimapCenter = camera->getPosition();
if (cameraController && cameraController->isThirdPerson()) if (cameraController && cameraController->isThirdPerson())
@ -851,11 +855,13 @@ void Renderer::beginFrame() {
minimap->compositePass(currentCmd, minimapCenter); minimap->compositePass(currentCmd, minimapCenter);
} }
// World map composite (renders zone tiles into 1024x768 render target) // World map composite (renders zone tiles into 1024x768 render target)
g_crashRenderPhase = "bf:worldmap";
if (worldMap) { if (worldMap) {
worldMap->compositePass(currentCmd); worldMap->compositePass(currentCmd);
} }
// Character preview composite passes // Character preview composite passes
g_crashRenderPhase = "bf:preview";
for (auto* preview : activePreviews_) { for (auto* preview : activePreviews_) {
if (preview && preview->isModelLoaded()) { if (preview && preview->isModelLoaded()) {
preview->compositePass(currentCmd, vkCtx->getCurrentFrame()); preview->compositePass(currentCmd, vkCtx->getCurrentFrame());
@ -863,15 +869,18 @@ void Renderer::beginFrame() {
} }
// Shadow pre-pass (before main render pass) // Shadow pre-pass (before main render pass)
g_crashRenderPhase = "bf:shadow";
if (shadowsEnabled && shadowDepthImage[0] != VK_NULL_HANDLE) { if (shadowsEnabled && shadowDepthImage[0] != VK_NULL_HANDLE) {
renderShadowPass(); renderShadowPass();
} }
// Water reflection pre-pass (renders scene from mirrored camera into 512x512 texture) // Water reflection pre-pass (renders scene from mirrored camera into 512x512 texture)
g_crashRenderPhase = "bf:reflection";
renderReflectionPass(); renderReflectionPass();
} // !skipPrePasses } // !skipPrePasses
// --- Begin render pass --- // --- Begin render pass ---
g_crashRenderPhase = "bf:renderpass";
// Select framebuffer: PP off-screen target or swapchain (§4.3 — PostProcessPipeline) // Select framebuffer: PP off-screen target or swapchain (§4.3 — PostProcessPipeline)
VkRenderPassBeginInfo rpInfo{}; VkRenderPassBeginInfo rpInfo{};
rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;